CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE 'langname' HANDLER call_handler LANCOMPILER 'comment'
TRUSTED はその言語の呼び出しハンドラが安全 であることを指定します。つまり、権限を持たないユーザには アクセス制限を越える機能を何も与えないということです。もし 言語を登録するときにこのキーワードが省略されると、 Postgres スーパーユーザ権限を持つ ユーザのみが新しい関数を作るためにこの言語を使うことができるように なります。
新しい手続き言語の名前です。言語名は大文字小文字が関係 ありません。手続き言語はどの Postgres の組み込み言語も重ねて定義することはできません。
call_handler は 以前登録されていた関数の名前で、 PL プロシージャを実行するために 呼び出されるものです。
LANCOMPILER 引数は、新しい pg_language エントリーの LANCOMPILER 属性に挿入されるための 文字列です。現時点では、Postgres はこの属性をどこにも使っていません。
Postgres ユーザは CREATE LANGUAGE を使って新しい言語を Postgresに登録することができます。 続いて、関数とトリガプロシージャはこの新しい言語で定義可能に なります。ユーザは新しい言語を登録するためには Postgres のスーパーユーザ 権限を持っていなければいけません。
Note: Postgres 7.1 以降では、呼び出しハンドラ は古い様式のインタフェースではなく、 "version 1" 関数管理者 インタフェースに忠実でなければなりません。
手続き言語の呼び出しハンドラは、 C のようなコンパイラ型 言語で書かれ、引数をとらず未定義の型を意味する opaque 型を返す関数として Postgres に登録されなければ なりません。これは呼び出しハンドラが関数として直接問い合わせ に呼び出されることを防ぎます。(しかし、言語内でハンドラによって 提供される PL 関数が実行されるべき時は、実際の呼び出しの際に引数が 供給されることもあります。)
呼び出しハンドラは他の関数と同じように呼び出されます。 呼び出される関数に関する情報と引数値を持つ構造体FunctionCallInfoData へのポインタを受け取り、Datum 結果を返すことを期待されています (そして SQL NULL の結果を返そうとする場合、できる限り FunctionCallInfoData 構造体の isnull フィールドを設定します。)呼び出しハンドラと通常の呼び出される 関数の違いは FunctionCallInfoData 構造体の flinfo->fn_oid フィールドが、 呼び出しハンドラ自身ではなく呼び出される PL 関数の OID を持つと いうことです。呼び出しハンドラはどの関数を実行するかを 決定するためにこのフィールドを使わなければなりません。更に、 渡される引数のリストは呼び出しハンドラではなく目標の PL 関数の宣言 に基づいて設定されます。
pg_proc エントリーを取り出し、呼び出された プロシージャの引数と返り値を分析するのは呼び出しハンドラ の役目です。プロシージャの CREATE FUNCTION からの AS 句は pg_proc テーブル エントリーの prosrc 属性の中にあります。 これは(PL/Tcl のような)手続き言語自身の中のソーステキスト、 ファイルへのパス名、もしくは呼び出しハンドラに何をすべきか 詳細に指示するほかのものかもしれません。
しばしば、SQL 文ごとに同じ関数が何度も呼び出されることがあります。 呼び出しハンドラは flinfo->fn_extra フィールドを使って呼び出される関数に関する情報が繰り返し検索すること を回避できます。このフィールドははじめは NULL ですが、 呼び出しハンドラによって PL 関数に関する情報を指すように設定 することができます。続く呼び出しでは、もし flinfo->fn_extra がすでに非 NULL である 場合はそれを使うことができ情報検索が飛ばされます。 呼び出しハンドラは flinfo->fn_extra が少なくとも現在の問い合わせが終るまでは生き続けるメモリを 指しているということに注意しなければなりません。 FmgrInfo データ構造体はそれほど長く保持することができるためです。 これをするための一つの方法として、 flinfo->fn_mcxt で指定される メモリコンテキストに余分なデータを割り当てることです。 そのようなデータは通常 FmgrInfo 自身と同じ寿命をもちます。 しかしハンドラは、問い合わせを越えて関数定義情報をキャッシュ できるように、更に長く生きるコンテキストの使用を 選ぶこともできます。
PL 関数がトリガとして呼び出されると、明示的な引数は何も 渡されませんが、FunctionCallInfoData の context フィールドは、はっきりとした関数呼出しの中にあるため NULL ではなく TriggerData ノードを指します。PL ハンドラは PL 関数が トリガ情報に到達するための仕組を提供するべきです。
関数を作成するためには CREATE FUNCTION を使います。
手続き言語を削除するためには DROP LANGUAGE を使います。
さらに詳しい情報は、テーブル pg_language を参照して下さい。
Table "pg_language" Attribute | Type | Modifier ---------------+---------+---------- lanname | name | lanispl | boolean | lanpltrusted | boolean | lanplcallfoid | oid | lancompiler | text | lanname | lanispl | lanpltrusted | lanplcallfoid | lancompiler -------------+---------+--------------+---------------+------------- internal | f | f | 0 | n/a C | f | f | 0 | /bin/cc sql | f | f | 0 | postgres
手続き言語の呼び出しハンドラは通常は C で書かれ、バックエンドに リンクされているか動的にロードされるかによって ‘内部'もしくは 'C'言語として登録されなければなりません。呼び出しハンドラは 古い様式の 'C' 関数インタフェースを使うことはできません。
現時点では、手続き言語の定義は一度作成されると変えることは できません。
これは C で書かれた PL ハンドラのテンプレートです。
#include "executor/spi.h" #include "commands/trigger.h" #include "utils/elog.h" #include "fmgr.h" #include "access/heapam.h" #include "utils/syscache.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" PG_FUNCTION_INFO_V1(plsample_call_handler); Datum plsample_call_handler(PG_FUNCTION_ARGS) { Datum retval; if (CALLED_AS_TRIGGER(fcinfo)) { /* * トリガプロシージャとして呼び出されます。 */ TriggerData *trigdata = (TriggerData *) fcinfo->context; retval = ... } else { /* * 関数として呼び出されます。 */ retval = ... } return retval; }
PL 呼び出しハンドラを完成させる点の代わりに、数千行のコード を追加するだけですみます。ロード可能なモジュールにコンパイル する方法は CREATE FUNCTION を見て下さい。
以下のコマンドはサンプルの手続き言語を登録します。
CREATE FUNCTION plsample_call_handler () RETURNS opaque AS '/usr/local/pgsql/lib/plsample.so' LANGUAGE 'C'; CREATE PROCEDURAL LANGUAGE 'plsample' HANDLER plsample_call_handler LANCOMPILER 'PL/Sample';