今日はインストール経過のメモで、画像が多いです。実行環境はWindows 7 32bit + PostgreSQL Portable 9.4.1 + WinPython 3.3.5.8。PL/Pythonの詳細はこちら(日本語ドキュメント内の章)を参照。簡単に言えばPostgreSQL内の自作関数がSQLだけでなくPythonでも書けるようになる、組み込み言語の一種です。

前にPostgreSQL 9.3Python 3.2.5を使って準備した時はどちらもポータブル版でなく、実行環境とデータを他へ移すのが面倒でしたが、PostgreSQL Portable 9.4をかなり使うようになったので、この際Python3もポータブル版で用意し、両者を組み合わせてPL/Pythonを使えるようにしました。
Contents

使うPythonのバージョン
Python2系と3系があるのと同様、PL/Python23があり、今回はタイトルにあるよう3を使います(というか最近のWindowsPostgreSQLPL/Python2を使う例を見たことがない)。

ポータブル版でも通常版(EnterpriseDB社のサイトにあるインストーラの意味)でも、Windows 32bit用のPostgreSQL9.4.1には、下のようにPL/Python3用のコンパイル済ライブラリが同梱されています。問題はマイナーバージョンで、前にPostgreSQL9.3で準備した時は、当時の最新の3.3では動かず3.2で動きました。

その時はライブラリの依存関係を調べる
Dependency Walkerを使って解決したので、今回は最初に行います。Dependency Walkerは上記リンク(公式サイト)から32bit用のVersion 2.2.6000をダウンロードし、適当なフォルダに解凍するだけ。plpython3.dllを開くと ↓ のようにPYTHON33.DLLが見つからないと出たので、Python 3.3を使えば良さそうと仮定して進めます。

ポータブルなPython 3.3の準備
これはメジャーなWinPythonから簡単に得られます。公式サイトは"without installing anything!", "Portable or not, the choice is yours!"等とポータビリティをアピールしていて今日の趣旨に合い、Python本体だけでなく各種パッケージ込みなのも良いです。ただその分ファイルサイズが大きく、今回ダウンロードしたWinPython-32bit-3.3.5.8.exe216MB、解凍すると1GB超。以下このexeファイルを実行した様子で、実際作業されることは指定フォルダへの解凍のみ。


解凍されたフォルダを開くと、PostgreSQLplpython3.dllが依存していたpython33.dllが確かにありました。次は、両者がつながるようにPostgreSQLサーバを起動させます。

PostgreSQL Portable起動バッチファイルの設定
基本は先々週作ったもの(ポータブル版PostgreSQL:起動・終了・再起動を一つのコンソールで)と同じで、実質追加するのは2つの環境変数だけで済みました。下がバッチファイル全体で、初めの方にあるset pythonhomeset pathがそれ。pythonhomeに先ほど確認したpython33.dllを含むフォルダを指定し、それをpathにコピーします。パスが通っている確認と、先々週のバッチと区別するのを兼ね、Pythonのバージョン表示を出すコマンドを入れました。
pg_ctl_and_python.batSelectRawtextBitbucket
@echo off

set ctl=App/PgSQL/bin/pg_ctl
set dir=Data/data
set pid=%dir%/postmaster.pid

:: set environmental variables for PL/Python3
set pythonhome=%~d0/AppsPortable/WinPython/WinPython-32bit-3.3.5.8/python-3.3.5
set path=%pythonhome%

:: indicate Python and its version
echo.
python -V
echo.

if exist "%pid%" (
    echo postmaster.pid exists and PostgreSQL have been started possibly.
    goto ask
) else (
    "%ctl%" -D "%dir%" -w start
)

:ask
set /p inp="press [R] to restart PostgreSQL, [Q] to quit : "
if "%inp%"=="R" (
    "%ctl%" -D "%dir%" -w restart
    goto ask
) else if "%inp%"=="Q" (
    "%ctl%" -D "%dir%" -w stop
    goto :eof
)
goto ask

バッチファイル内に記述したパス、またバッチ自身を置く場所は、実行環境によって変わります(というかユーザが自由に変えられるのがポータブル版の利点)。上の内容を前提にすると、バッチの場所は ↓ のようにPostgreSQL Portableの一番上になります。

設定内容が正しければ ↓ こんな感じでPostgreSQLが起動します(Windowsの黒いコマンドプロンプトでないのは、自分の単なるカスタマイズ)。コンソールからは、再起動(R)か終了(Q)または強制的にバッチを止めることだけができます。

pgAdminで接続、PL/Python3をインストール&テスト
以上が済めば、任意のデータベースでPL/Python3を使う準備が整います。以下、テスト用のデータベースで試した様子。最初にデータベースを作成した時点では、下のように組み込み言語(Language)にPL/Pythonがありません。必要に応じて、ExtensionというPostgreSQLの拡張機能管理の仕組みを使い、PL/Pythonを個々のデータべースからインストールorアンインストールします。

インストールはデータベース上でCREATE EXTENSION一文を実行するだけ。特に問題がなければ ↓ のようになります。なおEXTENSION名はplpython3u。実行後にpgAdminのオブジェクトブラウザを再描画すると(二つ目の画像)ExtensionsLanguages両方にPL/Pythonが出ます。


Hello Worldの代わりに、PostgreSQLDO文(無名コードブロック)を使ったテスト。簡単なものですが、実は同じ組み込み言語のPL/RではDO文が使えず、またWindows環境では日本語を直接変数に入れるとサーバがクラッシュしたので
(追記:回避方法が分かりました)、それと比べるとPL/Pythonの有難みを感じます。

Pythonなので当然、インデントがきちんとしていないとエラーになります。

PostgreSQL起動用バッチで、環境変数の設定を間違えた場合
PostgreSQL Portable起動時のバッチファイルのうち、PL/Pythonに必要だった環境変数の設定部分を下に再掲します。Pythonではもう一つPYTHONPATHが必要になることもありますが、今回はなくて大丈夫でした。今後何か問題が出たら追記します。
set pythonhome=%~d0/AppsPortable/WinPython/WinPython-32bit-3.3.5.8/python-3.3.5
set path=%pythonhome%

上の2行を忘れると、データベースにインストールしようとCREATE EXTENSION文を実行しても次のようなエラーになります。Python本体が見つかっていない状態。
ERROR:  could not load library "D:/AppsPortable/PostgreSQLPortable-9.4/App/PgSQL/lib/plpython3.dll": The specified module could not be found.

上の場合は単にCREATE EXTENSION一文が失敗するだけで済みますが、間違って環境変数の一つPYTHONHOMEを設定せず、PATHに直接Pythonのある場所を書いてパスだけ通すと、怖いことにCREATE EXTENSION実行の瞬間にPostgreSQLサーバが落ちます。下がその時のログで、エンコーディング用のモジュールが見つからず致命的なエラーになる模様。

pgAdmin側では ↓ こんなダイアログが出て切断されます。PL/Rで不用意に日本語を使った時はよくこうなるので
(追記:回避方法が分かりました)、 今回はそれほど驚きませんでした。