バージョンごとのドキュメント一覧

43.1. PL/Perl関数と引数 #

<title>PL/Perl Functions and Arguments</title>

To create a function in the PL/Perl language, use the standard <xref linkend="sql-createfunction"/> syntax: PL/Perl言語で関数を作成するには、以下の標準的なCREATE FUNCTION構文を使用してください。

CREATE FUNCTION funcname (argument-types)
RETURNS return-type

&#45;- function attributes can go here

-- 関数の属性はここに来る
AS $$

    # PL/Perl function body goes here

    # PL/Perl関数本体はここに来る
$$ LANGUAGE plperl;

The body of the function is ordinary Perl code. In fact, the PL/Perl glue code wraps it inside a Perl subroutine. A PL/Perl function is called in a scalar context, so it can't return a list. You can return non-scalar values (arrays, records, and sets) by returning a reference, as discussed below. 関数本体は通常のPerlのコードです。 実際、PL/Perlの糊付けコードは、これをPerlのサブルーチンの内部に格納します。 PL/Perl関数はスカラコンテキストとして呼び出されます。このためリストを返すことはできません。 後述の通り、参照を返すことによりスカラ以外の値(配列、レコード、集合)を返すことができます。

In a PL/Perl procedure, any return value from the Perl code is ignored. PL/Perlプロシージャでは、Perlコードからのあらゆる戻り値は無視されます。

PL/Perl also supports anonymous code blocks called with the <xref linkend="sql-do"/> statement: またPL/PerlはDO文で呼び出される匿名コードブロックをサポートします。

DO $$
    # PL/Perl code
$$ LANGUAGE plperl;

An anonymous code block receives no arguments, and whatever value it might return is discarded. Otherwise it behaves just like a function. 匿名コードブロックは引数を取りません。 また何らかの値を返したとしても破棄されます。 その他は関数と同様に動作します。

注記

The use of named nested subroutines is dangerous in Perl, especially if they refer to lexical variables in the enclosing scope. Because a PL/Perl function is wrapped in a subroutine, any named subroutine you place inside one will be nested. In general, it is far safer to create anonymous subroutines which you call via a coderef. For more information, see the entries for <literal>Variable "%s" will not stay shared</literal> and <literal>Variable "%s" is not available</literal> in the <citerefentry><refentrytitle>perldiag</refentrytitle></citerefentry> man page, or search the Internet for <quote>perl nested named subroutine</quote>. Perl、特にその閉ざされたスコープで局所変数を参照するような場合では、名前付きの入れ子状サブルーチンの使用は危険です。 PL/Perl関数はサブルーチン内に格納されますので、内部に記述した名前付きのサブルーチンはすべて入れ子にされます。 一般的に、コード参照を介して呼び出す匿名サブルーチンを作成する方がかなり安全です。 詳細はperldiagマニュアルページ内のVariable "%s" will not stay sharedおよびVariable "%s" is not availableを参照してください。 またはインターネットでperl nested named subroutineを検索してください。

The syntax of the <command>CREATE FUNCTION</command> command requires the function body to be written as a string constant. It is usually most convenient to use dollar quoting (see <xref linkend="sql-syntax-dollar-quoting"/>) for the string constant. If you choose to use escape string syntax <literal>E''</literal>, you must double any single quote marks (<literal>'</literal>) and backslashes (<literal>\</literal>) used in the body of the function (see <xref linkend="sql-syntax-strings"/>). CREATE FUNCTIONコマンドの構文では、関数本体は文字列定数として記述されることを必須としています。 通常、文字列定数にはドル引用符付け(4.1.2.4を参照)を使用することが最も便利です。 エスケープ文字列構文E''を使用することを選択した場合、関数本体で使用される単一引用符(')とバックスラッシュ(\)をすべて二重にしなければなりません(4.1.2.1を参照)。

Arguments and results are handled as in any other Perl subroutine: arguments are passed in <varname>@_</varname>, and a result value is returned with <literal>return</literal> or as the last expression evaluated in the function. 引数と結果は他のPerlサブルーチンと同様に扱われます。 引数は@_の中に渡され、結果値はreturn、または、その関数で最後に評価された式として返されます。

For example, a function returning the greater of two integer values could be defined as: 例えば、2つの整数のうち大きな方を返す関数は以下のように定義できます。

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

注記

Arguments will be converted from the database's encoding to UTF-8 for use inside PL/Perl, and then converted from UTF-8 back to the database encoding upon return. PL/Perl内部での使用のため、引数はデータベースの符号化方式からUTF-8に変換され、返されるときにUTF-8からデータベースの符号化方式に戻されます。

If an SQL null value<indexterm><primary>null value</primary><secondary sortas="PL/Perl">in PL/Perl</secondary></indexterm> is passed to a function, the argument value will appear as <quote>undefined</quote> in Perl. The above function definition will not behave very nicely with null inputs (in fact, it will act as though they are zeroes). We could add <literal>STRICT</literal> to the function definition to make <productname>PostgreSQL</productname> do something more reasonable: if a null value is passed, the function will not be called at all, but will just return a null result automatically. Alternatively, we could check for undefined inputs in the function body. For example, suppose that we wanted <function>perl_max</function> with one null and one nonnull argument to return the nonnull argument, rather than a null value: 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 (not defined $x) {
        return undef if not defined $y;
        return $y;
    }
    return $x if not defined $y;
    return $x if $x > $y;
    return $y;
$$ LANGUAGE plperl;

As shown above, to return an SQL null value from a PL/Perl function, return an undefined value. This can be done whether the function is strict or not. 上で示した通り、PL/Perl関数からSQLのNULL値を返すためには、未定義値を返すようにしてください。 これは、関数が厳密かどうかに関係なく、実行することができます。

Anything in a function argument that is not a reference is a string, which is in the standard <productname>PostgreSQL</productname> external text representation for the relevant data type. In the case of ordinary numeric or text types, Perl will just do the right thing and the programmer will normally not have to worry about it. However, in other cases the argument will need to be converted into a form that is more usable in Perl. For example, the <function>decode_bytea</function> function can be used to convert an argument of type <type>bytea</type> into unescaped binary. 関数引数の内で参照ではないものは、対応するデータ型向けのPostgreSQLの標準的な外部テキスト表現で表された文字列です。 通常の数値やテキスト型では、Perlは正確に処理を行いますので、通常プログラマは心配することはありません。 しかし、この他の場合では、引数をPerlでより使用しやすいように変換する必要があります。 例えば、decode_bytea関数はbytea型の引数をエスケープしないバイナリに変換するために使用することができます。

Similarly, values passed back to <productname>PostgreSQL</productname> must be in the external text representation format. For example, the <function>encode_bytea</function> function can be used to escape binary data for a return value of type <type>bytea</type>. 同様に、PostgreSQLに戻される値を外部テキスト表現書式で表さなければなりません。 例えば、bytea型の戻り値をバイナリデータにエスケープするためにencode_byteaを使用することができます。

One case that is particularly important is boolean values. As just stated, the default behavior for <type>bool</type> values is that they are passed to Perl as text, thus either <literal>'t'</literal> or <literal>'f'</literal>. This is problematic, since Perl will not treat <literal>'f'</literal> as false! It is possible to improve matters by using a <quote>transform</quote> (see <xref linkend="sql-createtransform"/>). Suitable transforms are provided by the <filename>bool_plperl</filename> extension. To use it, install the extension: 特に重要な場合の1つは真偽値です。 つい先ほど述べたように、bool値のデフォルトの振舞いはPerlにテキストとして、すなわち't'または'f'で渡されるというものです。 Perlは'f'を偽とは扱いませんので、これは問題をはらんでいます。 変換(CREATE TRANSFORMを参照してください)を使って問題を改善することができます。 適切な変換がbool_plperl拡張で提供されています。 使うには、拡張をインストールします。


CREATE EXTENSION bool_plperl;  &#45;- or bool_plperlu for PL/PerlU

CREATE EXTENSION bool_plperl;  -- PL/PerlUに対してはbool_plperlu

Then use the <literal>TRANSFORM</literal> function attribute for a PL/Perl function that takes or returns <type>bool</type>, for example: 次にboolを受け取ったり返したりするPL/Perl関数に対してTRANSFORM関数属性を使います。例えば以下の通りです。

CREATE FUNCTION perl_and(bool, bool) RETURNS bool
TRANSFORM FOR TYPE bool
AS $$
  my ($a, $b) = @_;
  return $a && $b;
$$ LANGUAGE plperl;

When this transform is applied, <type>bool</type> arguments will be seen by Perl as being <literal>1</literal> or empty, thus properly true or false. If the function result is type <type>bool</type>, it will be true or false according to whether Perl would evaluate the returned value as true. Similar transformations are also performed for boolean query arguments and results of SPI queries performed inside the function (<xref linkend="plperl-database"/>). この変換が適用されると、bool引数はPerlからは1もしくは空、すなわち正しく真または偽と見えます。 関数の結果が型boolなら、Perlが戻り値を真と評価したかどうかに従って真または偽となります。 同様の変換は、関数の内部で行われる真偽値の問い合わせ引数やSPI問い合わせの結果(43.3.1)でも実行されます。

Perl can return <productname>PostgreSQL</productname> arrays as references to Perl arrays. Here is an example: 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();

Perl passes <productname>PostgreSQL</productname> arrays as a blessed <type>PostgreSQL::InServer::ARRAY</type> object. This object may be treated as an array reference or a string, allowing for backward compatibility with Perl code written for <productname>PostgreSQL</productname> versions below 9.1 to run. For example: PerlはPostgreSQLの配列をblessされたPostgreSQL::InServer::ARRAYオブジェクトとして渡します。 9.1より過去のPostgreSQLで作成されたPerlコードを実行させるための後方互換性のため、このオブジェクトは配列への参照または文字列として扱うことができます。 以下に例を示します。

CREATE OR REPLACE FUNCTION concat_array_elements(text[]) RETURNS TEXT AS $$
    my $arg = shift;
    my $result = "";
    return undef if (!defined $arg);


    # as an array reference

    # 配列への参照として
    for (@$arg) {
        $result .= $_;
    }


    # also works as a string

    # 文字列としても働く
    $result .= $arg;

    return $result;
$$ LANGUAGE plperl;

SELECT concat_array_elements(ARRAY['PL','/','Perl']);

注記

Multidimensional arrays are represented as references to lower-dimensional arrays of references in a way common to every Perl programmer. Perlプログラマの常識のように、多次元配列は低次元配列の参照への参照として表現されます。

Composite-type arguments are passed to the function as references to hashes. The keys of the hash are the attribute names of the composite type. Here is an example: 複合型の引数はハッシュへの参照として関数に渡されます。 ハッシュのキーは複合型の属性名です。 以下に例を示します。

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;

A PL/Perl function can return a composite-type result using the same approach: return a reference to a hash that has the required attributes. For example: 必要な属性を持つハッシュの参照を返すという同じ方法で、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();

Any columns in the declared result data type that are not present in the hash will be returned as null values. 宣言された結果データ型の任意の列の内、ハッシュ内に存在しないものはNULL値として返されます。

Similarly, output arguments of procedures can be returned as a hash reference: 同様に、プロシージャの出力引数はハッシュ参照で返すことができます。

CREATE PROCEDURE perl_triple(INOUT a integer, INOUT b integer) AS $$
    my ($a, $b) = @_;
    return {a => $a * 3, b => $b * 3};
$$ LANGUAGE plperl;

CALL perl_triple(5, 10);

PL/Perl functions can also return sets of either scalar or composite types. Usually you'll want to return rows one at a time, both to speed up startup time and to keep from queuing up the entire result set in memory. You can do this with <function>return_next</function> as illustrated below. Note that after the last <function>return_next</function>, you must put either <literal>return</literal> or (better) <literal>return undef</literal>. また、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;

For small result sets, you can return a reference to an array that contains either scalars, references to arrays, or references to hashes for simple types, array types, and composite types, respectively. Here are some simple examples of returning the entire result set as an array reference: 小規模な結果セットでは、それぞれ単純な型、配列型、複合型に対応する、スカラ、配列への参照、ハッシュへの参照を含む配列への参照を返すことができます。 以下に、配列への参照として結果セット全体を返す単純な例をいくつか示します。

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();

If you wish to use the <literal>strict</literal> pragma with your code you have a few options. For temporary global use you can <command>SET</command> <literal>plperl.use_strict</literal> to true. This will affect subsequent compilations of <application>PL/Perl</application> functions, but not functions already compiled in the current session. For permanent global use you can set <literal>plperl.use_strict</literal> to true in the <filename>postgresql.conf</filename> file. コード内でstrictプラグマを使用したいのであればいくつか選択肢があります。 一時的に大域的に使用するために、SET plperl.use_strictを真にすることができます。 このパラメータは、その後のPL/Perl関数のコンパイルに影響しますが、現在のセッションでコンパイル済みの関数には影響しません。 永続的に大域的に使用するためには、postgresql.confファイル内でplperl.use_strictを真に設定します。

For permanent use in specific functions you can simply put: 特定の関数で永続的に使用するためには単純に

use strict;

at the top of the function body. を関数本体の先頭に記載してください。

The <literal>feature</literal> pragma is also available to <function>use</function> if your Perl is version 5.10.0 or higher. また、Perlのバージョンが5.10.0以上であればusefeatureプラグマが利用可能です。