5

シナリオ

次のバージョンの PHP と PostgreSQL を実行する 2 つのシステム (サーバーではない)

  • フェドーラ 15:

    PHP

    PHP 5.3.13 (cli) (ビルド: 2012 年 5 月 9 日 14:38:35)
    Copyright (c) 1997-2012 The PHP Group
    Zend Engine v2.3.0、Copyright (c) 1998-2012 Zend Technologies
    pdo_pgsql
    PostgreSQL(libpq) バージョン9.0.7
    モジュールバージョン 1.0.2


    PostgreSQL


    CITEXT 拡張機能が有効になっているPostgreSQL 9.1.4 。

  • アーチリナックス:

    PHP

    PHP 5.4.6 (cli) (ビルド: 2012 年 8 月 16 日 12:50:09)
    Copyright (c) 1997-2012 The PHP Group
    Zend Engine v2.4.0、Copyright (c) 1998-2012 Zend Technologies
    pdo_pgsql
    PostgreSQL(libpq) バージョン9.1.4
    モジュールバージョン 1.0.2


    PostgreSQL


    CITEXT 拡張機能が有効になっているPostgreSQL 9.1.4 。


次のような単純なクエリの場合

select column1 from schema1.table1 where column1= ? 

column1 は CITEXT 型で、PHP PDO を介して実行されます

  • PHP 5.3.13、libpq 9.0.7 を使用する Fedora では、クエリは CITEXT で期待どおりに実行されます (大文字と小文字を区別しない検索が発生します)。
  • PHP 5.4.6、libpq 9.1.4 を使用する ArchLinux では、クエリが CITEXT で期待どおりに実行されません (大文字と小文字を区別する検索が発生します)。

PHP PDO ライブラリの新しいバージョンは、次のようなことをしていると思います。

select column1 from schema1.table1 where column1= 'value'::text;

バインディング中。

  • 私は正しいですか?
  • 回避策はありますか? それ以外の場合、大文字と小文字を区別しない検索の利点を得るために列のデータ型として CITEXT を使用しても、新しいバージョンの PDO を使用する場合は役に立ちません。

アップデート

ArchLinux で PHP 5.4.6,libpq 9.1.4 を使用して、ステートメント レベルのログ記録をオンにした後:

LOG:  execute pdo_stmt_00000001: select column1 from schema1.table1 where column1 = $1
DETAIL:  parameters: $1 = 'value'
LOG:  statement: DEALLOCATE pdo_stmt_00000001

列の実際の値column1は ですVALUE

まだ0要素で戻ってきます。

声明のとき

select column1 from schema1.table1 where column1 = 'value';

プロンプトで直接実行されPSQL、単一の行が返されます。

 column1  
---------
  VALUE
 (1 row)

したがって、型キャストは行われません! PDO/の動作はまだ理解できませんpostgresql


更新 2012-08-27 16:15:43.669142+00 (UMT + 0)

ステートメントを準備せずにクエリを直接実行しようとした後。

テストに使用したコードは次のとおりです。

try {
    $db = new PDO('pgsql:dbname=database1;user=user;password=pass;host=localhost');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $sql = "SELECT column1 from schema1.column1 where column1 = 'value'::citext ";
    $retval=$db->query($sql);
    foreach ($retval as $row) {
        print $row['uname'] . '<br>';
    }
}catch (PDOException $PDOerr) {
    echo 'An error occured : <br>';
    var_dump($PDOerr);
    exit;
    //some thing went wrong while performing the action on db.
    }

エラーが発生します:

object(PDOException)#10 (8) { ["message":protected]=> string(211) "SQLSTATE[42704]: \
Undefined object: 7 ERROR: type "citext" does not exist LINE 1: ...

citextが検出されない理由がわかりません。PSQLステートメントがプロンプトで直接実行されると、上記のようにすべてが正常に機能します。


最終更新

ログインしようとしていたユーザーの検索パスの問題でした。他のスキーマに対してセッション単位で実行したときにユーザーを作成しset search_path、デフォルトの '"$user",public' の代わりに他のスキーマに設定したと推測しています。ユーザーには、パブリック スキーマへのアクセス権がまったくありませんでした。Daniel Vérité私を正しい方向に向けてくれてありがとう。

ところで、ALTER ROLE user SET search_path TO "$user",public;検索パスを設定するために使用されます。ただし、現在のユーザーにちなんで名付けられたスキーマがないため、 $user は役に立ちません。

4

1 に答える 1

2
  1. なぜ推測するのですか?ステートメントのロギングをオンにして知ってください。
  2. バグだと思われる場合は、PDO プロジェクトにバグ レポートを提出するか、少なくともアーカイブのリストをチェックして、正当な理由があるかどうかを確認してください。
  3. 回避策として、次のようなことを試してください。

    c = (?)::citext

型定数はすべてのデータベースで共有されているように見えるので、運が悪いと思います

http://www.php.net/manual/en/pdo.constants.php

互換性を維持するために、ファイルシステム ライブラリが大文字の 8.3 のみをサポートするようにランク付けされた設計上の選択について、PDO チームにおめでとうと言いたいのは、ms-dos 6.22 でした。


明示的な DEALLOCATE は、以前に発行された PREPARE があったことを示唆しています。これは型指定されたパラメーターのリストを受け取るため、おそらくテキスト型がそこに設定されています。

于 2012-08-25T12:37:22.353 に答える