PHP + PostgreSQL で pg_prepare が失敗する原因を調べてみる修行

PHP + PostgreSQL で pg_prepare が失敗する現象に立ち向かってみる修行 - 昨日知ったこと続き。
config.log を見ると、

undefined reference to `PQprepare'
gcc -o conftest -I/usr/include -g -O2  -L/usr/lib  -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/usr/local/pgsql/lib conftest.c -lpq  -lrt -lmcrypt -lltdl -lresolv -lm -ldl -lnsl  -lxml2 -lz -lm -lxml2 -lz -lm

とある。configure 時の表示も

...
checking for PQprepare in -lpq... no
...

とある。
この時点で postgreSQL 関係の関数が、一部だけリンク失敗しているのは確実。で、そもそも postgreSQL が prepared statement に対応したビルドになっているかが心配になった。

が、psql を使って確かめたところ、問題なく prepared statement が使えた。config.log によれば /usr/local/pgsql/lib/libpq.a がおかしいわけだ。では、こいつに PQprepare は入っているのだろうか。

$ nm /usr/local/pgsql/lib/libpq.a | grep PQprepare
0000136c T PQprepare

いるらしい。じゃあ、ライブラリのパスが何か悪さしているのか。ということで、こんなファイルを作ってリンクのテスト。

$ cat tmp.c
int main() { PQprepare(); return 0; }
$ gcc -o tmp.x tmp.c -L/usr/local/pgsql/lib -lpq
$ gcc -o tmp.x tmp.c -L/usr/local/lib -L/usr/local/pgsql/lib -lpq
$ gcc -o tmp.x tmp.c -L/usr/lib -L/usr/local/lib -L/usr/local/pgsql/lib -lpq
/tmp/ccSoj6lv.o(.text+0x11): In function `main':
: undefined reference to `PQprepare'
collect2: ld はステータス 1 で終了しました

お、エラーになった。ってことは、/usr/lib/libpq.a がいるってことか ...

... あー、rpm で最初っから入っているやつ? 今気づくなんて遅すぎ ...。

$ rpm -qa | grep -i postgres
rh-postgresql-devel-7.3.4-8
rh-postgresql-libs-7.3.4-8

ああ、いらっしゃいましたね。/usr/libpq.a をリネームしたり、configure で工夫するより、これをアンインストールするのが簡単確実かな。

$ su - -c 'rpm --test -ev rh-postgresql-devel rh-postgresql-libs'
$ su - -c 'rpm -ev rh-postgresql-devel rh-postgresql-libs'

では、再度。

$ rm config.cache
$ make distclean
$ cat config.sh
./configure \
 --with-apxs2=/usr/local/apache2/bin/apxs \   
 --with-pgsql=/usr/local/pgsql \
 --enable-mbstring \
 --with-mcrypt
$ sh config.sh

configure 中に

checking for PQprepare in -lpq... yes

発見。

では、

$ make

でもって、make install はせずに、とりあえず .libs にできた libphp5.so を apache の modules の下にリネームしてコピー。でもって、そいつを libphp5.so としてシンボリックリンク
で、apache を再起動。
... 成功。

あとで make install するべきかな、面倒だけど。

それはそれとして、今まで php にリンクされていたのは PostgreSQL 7.3.4 のライブラリだったわけだ。インストールしたのは postgreSQL 8.1.3 だったのに。

教訓:競合するバージョンのものは最初にアンインストール

それにしても、勘がにぶってきているのに気づかされた。自分でもなさけない。
config.log に残っていた undefined reference とコンパイルコマンド行を見たときに気づかなきゃいかん。少なくとも /usr/local/pgsql/lib/libpq.a に問題がないことがわかった時点で、余計なライブラリがあることに気づかなければ ...。
衰えたなぁ。後進に道を譲るべきだな。

追記

phpinfo の情報では、PostgreSQL 8.1.3 だった。リンクされる libpq.a のバージョンではなく、php make 時のインクルードパスにある pg_config.h に定義された値が使われる模様。
実験。
pg_config.h の中の 8.1.3 をすべて 0.0.2 に書き換えて php を config & make。
で、sapi/cli/php -i | grep -i postgres
結果は

PostgreSQL Support => enabled
PostgreSQL(libpq) Version => 0.0.2

ということで、予想どおり。