40.3. データベースアクセス

PL/Python言語モジュールは自動的にplpyというPythonモジュールをインポートします。 このモジュールの関数と定数は、plpy.fooのように作成したPythonコードから使用することができます。 現在plpyでは、plpy.debug("msg")plpy.log("msg")plpy.info("msg")plpy.notice("msg")plpy.warning("msg")plpy.error("msg")、およびplpy.fatal("msg")関数を実装しています。 これらは、Cのコードからのelog(LEVEL, "msg")の呼び出しとほぼ同じです。 plpy.errorおよびplpy.fatalは、実際にPythonの例外を発生させます。 これが捕捉されない場合、PL/Pythonモジュールは、その関数ハンドラがPythonインタプリタから返る際にelog(ERROR, msg)を呼び出します。 Pythonインタプリタからのlong jumpは、おそらくあまり好ましくありません。 raise plpy.ERROR("msg")およびraise plpy.FATAL("msg")は、それぞれplpy.errorおよびplpy.fatalの呼び出しと同じです。

更に、plpyモジュールはexecuteおよびprepareという2つの関数を用意しています。 plpy.executeを、問い合わせ文字列および省略可能な制限引数を付けて呼び出すと、問い合わせが実行され、結果オブジェクトとして問い合わせ結果が返ります。 この結果オブジェクトはリストもしくは辞書オブジェクトを模擬します。 結果オブジェクトは、行番号や列名によってアクセスすることができます。 結果オブジェクトには、問い合わせ結果の行数を返すnrows()SPI_execが返す値を返すstatusというメソッドが追加されています。 結果オブジェクトは、変更することができます。

以下に例を示します。

rv = plpy.execute("SELECT * FROM my_table", 5)

これは、my_tableから5行までを返します。 my_tablemy_column列が存在する場合、その列には以下のようにアクセスできます。

foo = rv[i]["my_column"]

2番目の関数plpy.prepareは、問い合わせの実行計画を準備します。 問い合わせ内にパラメータ参照がある場合、問い合わせ文字列および引数型のリストとともに呼び出されます。 たとえば、以下のようにします。

plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", [ "text" ])

textは、$1として渡す変数の型です。 文を準備した後、それを実行するために関数plpy.executeを使用します。

rv = plpy.execute(plan, [ "name" ], 5)

3番目の引数は制限引数であり、省略可能です。

現在のバージョンでは、PL/Python関数の実行中にデータベースエラーが発生すると、サーバによってその関数は即座に終了させられます。 Pythonのtry ... catch構文を使用しても、エラー条件を捕捉することは不可能です。 例えば、plpy.execute()呼び出しに渡されたSQL文に構文エラーがあった場合、この関数は終了します。 この動作は、今後変更する予定です。

PL/Pythonモジュールを使用して準備した計画は自動的に保存されます。 これが何を意味するのかについてはSPIの文書(第41章)を参照して下さい。 これを複数呼び出しにおいて効果的に使用するためには、永続的な格納用辞書であるSDまたはGD(項40.1参照)のいずれかを使用する必要があります。 たとえば、以下のようにします。

CREATE FUNCTION usesavedplan() RETURNS trigger AS '
    if SD.has_key("plan"):
        plan = SD["plan"]
    else:
        plan = plpy.prepare("SELECT 1")
        SD["plan"] = plan
    # rest of function
' LANGUAGE plpythonu;