PHP Postgres PDO驱动程序不支持准备好的语句吗? [英] PHP Postgres PDO driver does not support prepared statement?

查看:147
本文介绍了PHP Postgres PDO驱动程序不支持准备好的语句吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是我迷失了方向,还是Postgres PDO驱动程序不仅仅支持准备好的语句,而是在客户端模拟它们?

Am I losing my mind, or does the Postgres PDO driver just not support prepared statements, but instead emulates them client side?

下面的代码即使对prepare()调用也不会返回错误.而是在调用execute()时返回适用的错误.

The following code returns NO ERROR for the prepare() call, even though it should. Instead, it returns the applicable error when execute() is called.

根据DanielVérité的说法,我错了,所以我添加了他的建议代码.我仍然会收到错误消息.现在,我的代码如下所示,并添加了Daniel的代码行.

Since according to Daniel Vérité I'm wrong, I added his suggested code. I still get the error. My code now looks like the below, with Daniel's line added.

<?php
$pdo = new PDO("pgsql:host=myhost;dbname=mydatabase");

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);  // as suggested by Daniel

$sth = $pdo->prepare('COMPLETE GARBAGE');
echo "[prepare] errorInfo = " . print_r($sth->errorInfo(), true);

$sth->execute();
echo "[execute] errorInfo = " . print_r($sth->errorInfo(), true);

PHP版本5.3.15,PHP Postgres客户端版本9.1.4,Postgres服务器版本9.2.1.

PHP version 5.3.15, PHP Postgres client version 9.1.4, Postgres server version 9.2.1.

推荐答案

请参见 http://www. php.net/manual/en/pdo.prepare.php

注意:

模拟的准备好的语句无法与数据库通信 服务器,因此PDO :: prepare()不会检查该语句.

Emulated prepared statements does not communicate with the database server so PDO::prepare() does not check the statement.

(实际上,实际准备好的语句不会立即发送,请参见下面对第二个问题的回答)

(in fact real prepared statements are not sent immediately anyway, see answer to Q2 below)

无论如何您都可以发出:

Anyway you may issue:

$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); 

获取使用SQL PREPARE命令实现的真实准备语句. 参见 http://www.php.net/manual/en/pdo.setattribute.php 更多.

to get real prepared statements implemented with the SQL PREPARE command. See http://www.php.net/manual/en/pdo.setattribute.php for more.

在进一步的讨论和测试中,出现了两个问题:

On further discussion and tests, two questions arise:

问题1.为什么pdo::getAttribute(PDO::ATTR_EMULATE_PREPARES)会产生错误?
确实setAttribute不会出错,但是getAttribute(PDO::ATTR_EMULATE_PREPARES)表示:

Q1. Why does pdo::getAttribute(PDO::ATTR_EMULATE_PREPARES) yield an error?
Indeed setAttribute doesn't error out but getAttribute(PDO::ATTR_EMULATE_PREPARES) says:

'SQLSTATE [IM001]:驱动程序不支持此功能:驱动程序支持 不支持该属性"

'SQLSTATE[IM001]: Driver does not support this function: driver does not support that attribute'

查看 pdo :: getAttribute 的文档,它显示常量适用于数据库连接的内容如下,并且从PDO::ATTR_AUTOCOMMITPDO::ATTR_TIMEOUT跟随着许多常量,值得注意的是PDO::ATTR_EMULATE_PREPARES不在其中 .因此严格来说,我们不应该期望getAttribute(PDO::ATTR_EMULATE_PREPARES)正常工作.

Looking at the documentation for pdo::getAttribute, it says The constants that apply to database connections are as follows, and a number of constants follow from PDO::ATTR_AUTOCOMMIT to PDO::ATTR_TIMEOUT, and it's remarkable that PDO::ATTR_EMULATE_PREPARES is not in them. So strictly speaking, we should not expect getAttribute(PDO::ATTR_EMULATE_PREPARES) to work, anyway.

现在可以肯定地查看源代码,看来pdo_pgsql驱动程序提供了pdo_pgsql_get_attribute函数,该函数在以下位置具有switch语句:

Now looking at the source code to be sure, it appears that the pdo_pgsql driver provides a pdo_pgsql_get_attribute function that has a switch statement on:

  • PDO_ATTR_CLIENT_VERSION
  • PDO_ATTR_SERVER_VERSION
  • PDO_ATTR_CONNECTION_STATUS
  • PDO_ATTR_SERVER_INFO

就是这样.没有PDO_ATTR_EMULATE_PREPARES的踪迹,这就是最终出现此错误的原因.

and that's it. No trace of PDO_ATTR_EMULATE_PREPARES which is why ultimately this error appears.

另一方面,函数pdo_pgsql_set_attr在以下位置具有switch语句:

On the other hand, the function pdo_pgsql_set_attr has a switch statement on:

  • PDO_ATTR_EMULATE_PREPARES
  • PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT

确认设置此属性后实际上已将其考虑在内. 因此,PDO与与setAttribute不匹配的getAttribute不一致.

which confirms that this attribute is actually taken into account when set. So PDO is just inconsistent with getAttribute that doesn't match setAttribute.

问题2-当准备仿真为假时,为什么伪造的语句在准备好时不立即引发错误?

pgsql_statement.c中考虑以下代码:

        if (!S->is_prepared) {
stmt_retry:
            /* we deferred the prepare until now, because we didn't
             * know anything about the parameter types; now we do */
            S->result = PQprepare(H->server, S->stmt_name, S->query, 
                        stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0,
                        S->param_types);

它表明使用了PQprepare(因此这是一个真实的"准备好的语句),而且该语句没有立即发送到服务器.这就是dbo::prepare("bogus statement")不会返回false的原因:由于缺少参数类型,它实际上并未发送到服务器.

It shows that PQprepare is used (so that's a "real" prepared statement), but also that the statement is not immediately sent to the server. That's why the dbo::prepare("bogus statement") won't return false: it's actually not sent to the server for lack of parameter types.

这篇关于PHP Postgres PDO驱动程序不支持准备好的语句吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆