PL/Pythonで作成された関数は標準的なCREATE FUNCTION構文で宣言されます。
CREATE FUNCTIONfuncname
(argument-list
) RETURNSreturn-type
AS $$ # PL/Python function body $$ LANGUAGE plpython3u;
関数本体は単なるPythonスクリプトです。
関数が呼び出されると、引数はargs[]
リストの要素として渡されます。
名前付きの引数も通常の変数としてPythonスクリプトに渡されます。
通常、名前付き引数の方が可読性が高くなります。
結果は、Pythonコードから通常の方法、return
またはyield
(結果セット文の場合)で返されるものです。
戻り値を提供しない場合、PythonはデフォルトのNone
を返します。
PL/PythonはPythonのNone
をSQLのNULL値に変換します。
プロシージャでは、Pythonコードからの結果はNone
でなければなりません(典型的にはreturn
文を使わずプロシージャを終了したり、return
文を引数無しで使うことで達成されます)。
さもないとエラーが起きます。
たとえば、2つの整数の内大きな数を返す関数は以下のように定義することができます。
CREATE FUNCTION pymax (a integer, b integer) RETURNS integer AS $$ if a > b: return a return b $$ LANGUAGE plpython3u;
関数定義の本体として提供されたPythonのコードはPythonの関数に変換されます。 例えば上の例は以下のようになります。
def __plpython_procedure_pymax_23456(): if a > b: return a return b
ここで、23456はPostgreSQLにより割り当てられたこの関数のOIDです。
引数はグローバル変数として設定されます。 Pythonのスコープ規則のため、これは、ブロック内でグローバルとして再宣言されていない限り、関数内で引数変数に変数名自身を含む式の値として再代入できないという難解な結果をもたらします。 例えば以下は動作しません。
CREATE FUNCTION pystrip(x text) RETURNS text AS $$ x = x.strip() # error return x $$ LANGUAGE plpython3u;
x
への代入は、x
をブロック全体に対するローカル変数にしようとし、そして、代入の右辺のx
がPL/Pythonの関数パラメータではなく、まだ割り当てられていないローカル変数x
を参照するためです。
global
文を使用することで、動作するようになります。
CREATE FUNCTION pystrip(x text) RETURNS text AS $$ global x x = x.strip() # ok now return x $$ LANGUAGE plpython3u;
しかし、PL/Pythonのこうした詳細な実装に依存しないようにすることを勧めます。 関数パラメータは読み取りのみとして扱うことを勧めます。