WorkAround for PHP PDO(带有libpq V 9.1.4)绑定以使用CITEXT


WorkAround for PHP PDO(with libpq V 9.1.4) binding for use of CITEXT?

场景

两个系统(非服务器)运行PHP和PostgreSQL,具有以下版本

  • Fedora 15:

    PHP

    PHP 5.3.13(cli)(构建时间:2012年5月9日14:38:35)
    版权所有(c)1997-2012 PHP集团
    Zend Engine v2.3.0,版权所有(c)1998-2012 Zend Technologies
    pdo_pgsql
    PostgreSQL(libpq)9.0.7版
    模块版本1.0.2


    PostgreSQL

    PostgreSQL 9.1.4
    启用CITEXT扩展。

  • ArchLinux:

    PHP

    PHP 5.4.6(cli)(构建时间:2012年8月16日12:50:09)
    版权所有(c)1997-2012 PHP集团
    Zend Engine v2.4.0,版权所有(c)1998-2012 Zend Technologies
    pdo_pgsql
    PostgreSQL(libpq)9.1.4版
    模块版本1.0.2


    PostgreSQL

    PostgreSQL 9.1.4
    启用CITEXT扩展。


当诸如之类的简单查询

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;

在绑定期间。

  • 我说得对吗
  • 有变通办法吗?否则,在使用较新版本的PDO时,使用CITEXT作为列数据类型以获得不区分大小写搜索的优势是无用的

更新

打开语句级登录后,在带有PHP 5.4.6、libpq 9.1.4的ArchLinux上:

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

其中列CCD_ 1的实际值为CCD_。

仍然返回0个元素。

当语句

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

直接在CCD_ 3提示符上执行。

 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é为我指明了正确的方向。

BTW使用column10来设置搜索路径。尽管如此,$user是无用的,因为我没有任何以当前用户命名的模式。

  1. 为什么要猜测?打开语句日志记录并知道
  2. 如果您认为这是一个错误,请向PDO项目提交一份错误报告,或者至少检查列表档案,看看是否有充分的理由
  3. 尝试以下方法作为变通方法。

    c=(?)::citext

我猜你会倒霉的,因为看起来所有dbs 的类型常量都是共享的

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

祝贺PDO团队的设计选择,使您的文件系统库只支持大写8.3以保持兼容性是ms dos 6.22


明确的DEALLOCATE表明早些时候发布了PREPARE。这将需要一个类型化参数的列表,因此推测文本类型是在那里设置的。

  • http://www.postgresql.org/docs/current/static/sql-prepare.html
  • http://www.postgresql.org/docs/current/static/sql-deallocate.html