场景
两个系统(非服务器)运行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使用column1
0来设置搜索路径。尽管如此,$user是无用的,因为我没有任何以当前用户命名的模式。
- 为什么要猜测?打开语句日志记录并知道
- 如果您认为这是一个错误,请向PDO项目提交一份错误报告,或者至少检查列表档案,看看是否有充分的理由
-
尝试以下方法作为变通方法。
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