2006年11月 8日 (水)

[PHP]PDOではまったこと

PHPのPDOで開発を行っていますが、基本的にWindows環境で試験などを行っています。それでたまにLinux上で試験を実行してみととたんに動かなくなることがあります。今日は、ちょっとした思い込みで動かないことになってしまっていたのでそのことを書いておきます。

データベースからデータを取り込むときにPDOを使用している場合、

$db = new PDO( 'pgsql:host=localhost port=5432 dbname=testdb user=bruce password=mypass' );
$stmt = $db->prepare( 'SELECT * FROM testtable WHERE id = :id' );
$stmt->execute( array( ':id'=>$id ) );
$result = $stmt->fetch( PDO::FETCH_ASSOC );

というような一度、「prepare」をしてクエリーの発行準備をおこなってそれから「execute」にパラメータを渡して実際の実行を行うといった書き方をします。

ここまでは、別に何ということもないのですが、複数のパラメータを「execute」に渡すときに落とし穴がありました。

たとえば

$stmt = $db->prepare( 'SELECT * FORM shouhin WHERE price > :min AND price < :max';
$stmt->execute( array( ':min'=>10000, ':max'=>50000 );
$result = $stmt->fetchAll( PDO::FETCH_ASSOC );

というような別の値をとるような変数がある場合は問題ないのですが、同じ値を使う場合、何も考えないで

$stmt = $db->prepare( 'SELECT * FORM seiseki WHERE kokugo = :tensu AND sansu = :tensu';
$stmt->execute( array( ':tensu'=>100 );
$result = $stmt->fetchAll( PDO::FETCH_ASSOC );

という感じに「tensu」を使いまわしてクエリーを発行しようとしました。これは、Windows版で実行すると問題なく国語と算数の点数が100点のデータを取得できるのですが、Linux版に持っていくとクエリーエラーが発生して落ちてしまいます。

よくよくドキュメントを見てみるときちんと「prepare」の中にも書かれていましたし、オンラインのドキュメントの囲みの中で書かれていますがこちらにも同じようにはまった人がいたようです。

つまりは、

$stmt = $db->prepare( 'SELECT * FORM seiseki WHERE kokugo = :kokugo AND sansu = :sansu';
$stmt->execute( array( ':kokugo'=>100, ':sansu'=>100 );
$result = $stmt->fetchAll( PDO::FETCH_ASSOC );

といった感じに同じ値を使うのでもそれぞれ別の名前として使用しろということらしいです。

まあ、いろいろとありましたが結論としてはきちんとドキュメントに目を通せということなんでしょうけど、どう考えても「prepare」に名前をつけれるのであれば使い回しができてもよさそうな気がします。

| | コメント (0) | トラックバック (0)

2006年10月26日 (木)

[PHP]PDOでPostgreSQLを操作したときのエラー

PHPとPostgerSQLを使用してアプリケーションを開発していますが、そのときにLinux版でのみエラーが発生するということがありました。

PostgreSQLの設定でログを出力するように設定していて気がついたのですが、Windows版では、問題なくクエリーの発行が行われて正常に終了していました。そこでOSをFedora Core 5に変えてその上で同様に試験をしていたところあるパターンでのみ、登録処理がうまくいきませんでした。

クエリーのログとしては、

LOG:  statement: DEALLOCATE pdo_pgsql_stmt_09b83bd4
ERROR:  prepared statement "pdo_pgsql_stmt_09b83bd4" does not exist

といった内容で、どうやら発行したクエリーの解除を行っているのですが、そもそも発行していないクエリーの解除を行っているためにエラーが発生して処理が終わっていることがわかりました。
そもそも、そんな操作はいらないんですが^^;

そこでPHPのバグリポートの中をチェックするとどうやら同じような不具合を発見することができました。

そのバグリポートを見てみるとPostgreSQLのPDOのドライバにバグがあるらしくて、パッチを当てれば動作することがわかりました。

そこから、いろいろとパッチを当ててビルドするのにいろいろ大変でしたが(それは、また次の機会に)、パッチを当てて動作を確認したところ問題なく動作して余計なクエリーの解除をしないようになりました。

まだまだ、調べていくとまだまだPostgreSQLのPDOドライバはできがよろしくないようなので別の問題が発生するかもしれません。

[追記 2006/10/26 21:18]
ここで使用しているPHPのバージョンは、5.1.6で、PostgreSQLは8.1.4です。

| | コメント (0) | トラックバック (0)