一般的なWindowsPostgreSQL(EnterpriseDB社による
インストーラzip)にはPL/Python3が同梱されており、別途Python3を準備し環境変数を設定すれば組み込み言語としてすぐ使えます(例えば昨年末の記事)。

一方、Python2WinPostgresに組み込むことは、既成環境や情報がほとんどなく今まで避けてきました。でもPython3より2がまだまだ多いので
(例えば先日紹介したpgAdmin4など)できれば準備しておきたい。という訳で前々回から使い始めたMSYS2 + MinGW-w64のポータブル環境でビルド&インストールを試み、一応できたので以下手順です。途中の一部で管理者権限が必要。

なおCygwinでは、
パッケージにPL/Python2があるので(もちろんPython2PostgreSQLも)簡単に環境構築できます。別記事でそのうち。

Contents



実行環境(前回までのまとめ)

OSWindows7 x64で、MSYS2 + MinGW-w64はポータブルなmsys2-base-x86_64-20160205.tar.xzをダウンロード&解凍。フォルダ構成は ↓ こんな感じで、主なプログラムの場所(bin)がMinGWMSYS2ヶ所に分かれてます。
MSYS2_ROOT
 |-- dev
 |-- etc
 |-- home
 |-- mingw64
 |  |-- bin
 |
 |-- opt
 |-- tmp
 |-- usr
 |  |-- bin
 |
 |-- var


MSYS2のルートからコマンドプロンプトを起動し ↓ を打ってシェルに。他のターミナルを使ってbashの設定等をしてもいいけど、本題でないので省略。PostgreSQLのビルドに最低限必要な3つのパッケージをインストール。
> set HOME=/home             # 個人的なもの. Winのユーザ名を使わないため 
> set MSYSTEM=MINGW64
> usr\bin\bash --login -i    # -i なくても同じ
$ pacman -S mingw-w64-x86_64-toolchain    # この中にPython2あり
$ pacman -S make
$ pacman -S mingw-w64-x86_64-libxml2


PostgreSQL 9.5.3のソースをダウンロード&解凍してビルド。最初に本体を、続いて付属する拡張モジュール(contrib内)を。
$ cd POSTGRES_SOURCE
$ ./configure --enable-nls --host=x86_64-w64-mingw32 --with-libxml
$ make
$ make install
$ cd contrib
$ make
$ make install


結果こんな風に ↓ インストールされます。
MSYS2_ROOT
 |-- usr
   |-- local
      |-- pgsql
        |-- bin
        |-- include
        |-- lib
        |-- share


pgsqlフォルダを好きな場所に移し、mingw64/binから ↓ の4つのDLLpgsql/binにコピー。これでMSYS2 + MinGW-w64環境への依存なく起動できます(私製ポータブル版PostgreSQLの完成)。
libintl-8.dll
libiconv-2.dll
libxml2-2.dll
zlib1.dll


以上が
前々回(本体まで)前回(contrib)の経過。この開発・実行環境を用いて、次項からPL/Python2を使えるようにします。



ビルド前の準備(1)pexports.exe

PostgreSQLconfigureには--with-pythonというオプションがあり、PL/Pythonのビルドに先立ってこのオプション付きで本体からビルドし直します(そうしなくて済むやり方が今回見つからなかった)。クライアントツールなどやり直し不要なのもあるので、サーバ本体だけ。
$ make distclean
$ ./configure --enable-nls --host=x86_64-w64-mingw32 --with-libxml --with-python
$ cd src/backend
$ make


次にPL/Python2makeしようとすると ↓pexports.exeがないとエラー。当該のコマンドを見るとC:/Windows/system32/python27.dllも必要と分かります(MSYS2に入ってるPythonのバージョンによってファイル名は変わる)。
$ cd src/pl/plpython
$ make
...
pexports C:/Windows/system32/python27.dll > python27.def
/bin/sh: pexports: command not found
Makefile:57: recipe for target 'python27.def' failed
make: *** [python27.def] Error 127
make: *** Deleting file 'python27.def'


pexportsのパッケージがpacmanで見つからないので、ウェブ検索してソースからビルドします。下記サイトからpexports-0.47-mingw32-src.tar.xzをダウンロードし、特に問題なく完了。
» Index of /m/mi/mingw/MinGW/Extension/pexports/
$ cd PEXPORTS_SOURCE
$ ./configure
$ make
$ make install
$ pexports -v    # check result 



ビルド前の準備(2)python27.dll

MSYS2にはpython27.dllがないので(Python本体はあるけど)ソースからビルドすれば作られるかな?と思い、公式サイトからPython-2.7.11.tar.xzをダウンロード・解凍してやってみると ↓ 何故かmakeでエラー…。
$ cd PYTHON-2.7.11-SOURCE
$ ./configure
$ make
gcc -c -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-protot
ypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Modules/python.o ./Modules/
python.c
In file included from Include/Python.h:58:0,
                 from ./Modules/python.c:3:
Include/pyport.h:207:5: error: #error "Python doesn't support sizeof(pid_t) > si
zeof(long)"
 #   error "Python doesn't support sizeof(pid_t) > sizeof(long)"
     ^
Makefile:645: recipe for target 'Modules/python.o' failed
make: *** [Modules/python.o] Error 1


調べても解決の糸口がないので、
612日の記事と同様にMSI形式のインストーラを展開してDLLだけ使用。マイナーバージョンも同じ2.7.1164bit版を持ってきます。以下、DLLc:/windows/system32に持っていくまで管理者権限が必要。
(download: //www.python.org/downloads/
           -> Python 2.7.11
           -> python-2.7.11.amd64.msi)
> start /wait msiexec /a python-2.7.11.amd64.msi targetdir="展開先(絶対パス)" /qn
> copy 展開先/python27.dll c:\windows\system32


MSIを展開する際、一時ディレクトリc:/config.msiが作られます。展開後は空になって使わないので消去。展開先のルート ↓ にあるpython27.dllをコピー。


今回はしませんでしたが、PL/PythonMakefileDLLの場所が設定されており ↓ これを修正すれば、c:/windows/system32以外にコピーできたと思います。
...
# Python on win32 ships with import libraries only for Microsoft Visual C++,
# which are not compatible with mingw gcc. Therefore we need to build a
# new import library to link with.
ifeq ($(PORTNAME), win32)

pytverstr=$(subst .,,${python_version})
PYTHONDLL=$(subst \,/,$(WINDIR))/system32/python${pytverstr}.dll
...



ビルド、ポータブル版PostgreSQLへインストール

↓ こんどはOK。なおpexports、python27.dllがあってもサーバ本体がmakeされてないと、PL/Python単独でのmakeは不可でした。
$ cd POSTGRES_SOURCE/src/pl/plpython
$ make
$ make install


もうc:/windows/system32下にコピーしたDLLは不要。残ったままだと後々面倒なので消しときます(他の場所にあるDLLより優先して使われ、ポータブル版の動作を錯覚させる)。またMSYS2もビルドが終わったので今日の役割は終わり。後はコマンドプロンプト上の作業だけ。

make installの結果、MSYS2/usr/local/pgsql下の3つのフォルダ(include、lib、share)にPL/Python用のファイル群が配置されます。 ↓


このファイル群を、
前回までのポータブル版PostgreSQL(contrib追加済)に手動でコピー。PL/Pythonを使うのに最低限必要なのはlibshare/extensionフォルダ。コピー先の配置で示すと ↓ こんな感じです。
pgsql
 |-- bin
 |-- data
 |-- include
 |-- lib
 |  |-- plpython2.dll
 |-- share 
    |-- extension
      |-- plpython2u.control
      |-- plpython2u--1.0.sql
      +-- plpython2u--unpackaged--1.0.sql


続いてPython2を上記フォルダ内にコピー。離れた所にあってもいいけど、PostgreSQLと一緒に持ち運べる「専用のポータブル版Python」にしておくと便利なので。最低限必要なのはpython27.dllとライブラリ群。後者は、MSYS2内のmingw64/lib/python2.7フォルダをリネームして持ってきます。あと一応Python単独でも使えるようexeも。最終的な結果で示すと ↓ こう。
pgsql
 |-- bin
 |-- data
 |-- include
 |-- lib
 |-- python27
   |-- python27.dll
   |-- python.exe
   +-- lib    <== mingw64/lib/python2.7/* 
 |-- share 


以上でインストール終了。次で動作確認します。



環境変数を設定してサーバ起動、動作確認

PostgreSQLbinフォルダからコマンドプロンプトを起動し、2つの環境変数(PATH、PYTHONPATH)を ↓ のように設定します。PATHは既存のに加えてもOK。
> cd PG_BINDIR
> set PATH=../python27
> set PYTHONPATH=../python27/lib


binフォルダの位置からPythonの起動を ↓ 確認。これが駄目だとPostgreSQLサーバからPythonを認識できず、PL/Pythonを使えません。
> python
Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec  5 2015, 20:40:30) [MSC v.1500 64 bit (AMD64)] on win32 
Type "help", "copyright", "credits" or "license" for more information.
>>>


続いてサーバをアドホックに(サービスでなく)起動。pg_ctlのオプションは、ここでは最低限必要なデータフォルダの位置だけ。
> pg_ctl -D ../data start


クライアントは何でもよく、今回は同じbinフォルダ内のpsqlを使用。テスト用のデータベース(ここではplpy2)を作り、PL/Python2を入れます。EXTENSION名の末尾にuを忘れずに(untrustedの意味)。エラーなくCREATE EXTENSIONと出ればOK。
> psql -U postgres
# create database plpy2;
# \c plpy2
# create extension plpython2u;
CREATE EXTENSION


↓ とりあえず無名コードブロックでテスト。print文の代わりのplpy.info(PL/Python独自の関数)を使って画面表示しています。
# do language plpython2u
  $$
      plpy.info(1);
  $$;
INFO:  1
CONTEXT:  PL/Python anonymous code block
DO


Pythonモジュールを読めるかテスト。サーバ起動前に設定したPYTHONPATHの場所にあるモジュールは、基本的に使えるはずです。
# do language plpython2u
  $$
      import sys
      plpy.info(sys.version_info)
  $$;

  do language plpython2u
  $$
      import sys
      plpy.info(sys.platform)
  $$;


今回MinGW-w64Pythonをビルドできなかったのは残念だけど、一応WindowsPL/Python2を使えるようになりました。現時点でのPostgreSQLフォルダの全サイズ(contrib、Python、データを含む)は ↓ まだ200MB足らず。十分ポータブルに使えます。