5

场景

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

  • 软呢帽 15:

    PHP

    PHP 5.3.13 (cli) (built: May 9 2012 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

    PostgreSQL 9.1.4
    启用 CITEXT 扩展。

  • ArchLinux:

    PHP

    PHP 5.4.6 (cli) (built: Aug 16 2012 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

    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 作为列数据类型来获得不区分大小写搜索的优势是没有用的。

更新

开启语句级登录后,在 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é为我指明正确的方向。

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

4

1 回答 1

2
  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。这将需要一个类型参数列表,因此大概是在那里设置了文本类型。

于 2012-08-25T12:37:22.353 回答