PHP PDO的WorkAround(使用libpq V 9.1.4)绑定使用CITEXT?

Thi*_*key 5 php postgresql postgresql-9.1

场景

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

  • Fedora 15:

    PHP

    PHP 5.3.13(cli)(建于2012年5月9日14:38:35)
    版权所有(c)1997-2012 PHP Group
    Zend Engine v2.3.0,Copyright(c)1998-2012 Zend Technologies
    pdo_pgsql
    PostgreSQL(libpq)Version 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 Group
    Zend Engine v2.4.0,版权所有(c)1998-2012 Zend Technologies
    pdo_pgsql
    PostgreSQL(libpq)Version 9.1.4
    模块版本1.0.2


    PostgreSQL的

    PostgreSQL 9.1.4
    启用CITEXT扩展.


当一个简单的查询,如

select column1 from schema1.table1 where column1= ? 
Run Code Online (Sandbox Code Playgroud)

其中column1的类型为CITEXT,通过PHP PDO执行

  • 在使用PHP 5.3.13,libpq 9.0.7的Fedora上,查询按照CITEXT的预期执行(发生不区分大小写的搜索).
  • 在ArchLinux上使用PHP 5.4.6,libpq 9.1.4时,查询无法按预期执行CITEXT(发生区分大小写的搜索).

我猜测更新版本的PHP PDO库正在做类似这样的事情:

select column1 from schema1.table1 where column1= 'value'::text;
Run Code Online (Sandbox Code Playgroud)

在绑定期间.

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

更新

在转换语句级别登录后,在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
Run Code Online (Sandbox Code Playgroud)

列的实际值column1VALUE.

仍然回来0元素.

当声明

select column1 from schema1.table1 where column1 = 'value';
Run Code Online (Sandbox Code Playgroud)

直接在PSQL提示符上执行,返回单行.

 column1  
---------
  VALUE
 (1 row)
Run Code Online (Sandbox Code Playgroud)

因此,不会发生类型铸造!我仍然无法理解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.
    }
Run Code Online (Sandbox Code Playgroud)

我收到错误:

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

我不明白为什么citext没有被发现!当语句直接在PSQL提示符上执行时,一切正常,如上所述.


最后更新

这是我尝试登录的用户的搜索路径问题.我猜我已经创建了用户,当我set search_path对一些其他模式进行会话时,而不是默认的"$ user",public'它被设置为另一个模式.用户根本没有对公共模式的任何访问权限.感谢Daniel Vérité我指出了正确的方向.

BTW,用于ALTER ROLE user SET search_path TO "$user",public;设置搜索路径.虽然,$ user没用,因为我没有以当前用户命名的任何模式.

Ric*_*ton 2

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

    c = (?)::citext

我猜你会运气不好,因为看起来类型常量是为所有数据库共享的

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

恭喜 PDO 团队做出的设计选择是让您的文件系统库仅支持大写 8.3 以保持兼容性,即 ms-dos 6.22


显式的 DEALLOCATE 表明之前已发布过 PREPARE。这将采用输入参数的列表,因此大概在那里设置了文本类型。