今日はインストール経過のメモで、画像が多いです。実行環境はWindows 7 32bit + PostgreSQL Portable 9.4.1 + WinPython 3.3.5.8。PL/Pythonの詳細はこちら(日本語ドキュメント内の章)を参照。簡単に言えばPostgreSQL内の自作関数がSQLだけでなくPythonでも書けるようになる、組み込み言語の一種です。
前にPostgreSQL 9.3とPython 3.2.5を使って準備した時はどちらもポータブル版でなく、実行環境とデータを他へ移すのが面倒でしたが、PostgreSQL Portable 9.4をかなり使うようになったので、この際Python3もポータブル版で用意し、両者を組み合わせてPL/Pythonを使えるようにしました。
Contents
使うPythonのバージョン
Pythonに2系と3系があるのと同様、PL/Pythonも2と3があり、今回はタイトルにあるよう3を使います(というか最近のWindows版PostgreSQLでPL/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.exeは216MB、解凍すると1GB超。以下このexeファイルを実行した様子で、実際作業されることは指定フォルダへの解凍のみ。
解凍されたフォルダを開くと、PostgreSQLのplpython3.dllが依存していたpython33.dllが確かにありました。次は、両者がつながるようにPostgreSQLサーバを起動させます。
PostgreSQL Portable起動バッチファイルの設定
基本は先々週作ったもの(ポータブル版PostgreSQL:起動・終了・再起動を一つのコンソールで)と同じで、実質追加するのは2つの環境変数だけで済みました。下がバッチファイル全体で、初めの方にあるset pythonhomeとset pathがそれ。pythonhomeに先ほど確認したpython33.dllを含むフォルダを指定し、それをpathにコピーします。パスが通っている確認と、先々週のバッチと区別するのを兼ね、Pythonのバージョン表示を出すコマンドを入れました。
@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のオブジェクトブラウザを再描画すると(二つ目の画像)ExtensionsとLanguages両方にPL/Pythonが出ます。
↓Hello Worldの代わりに、PostgreSQLのDO文(無名コードブロック)を使ったテスト。簡単なものですが、実は同じ組み込み言語の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で不用意に日本語を使った時はよくこうなるので(追記:回避方法が分かりました)、 今回はそれほど驚きませんでした。