使用PostgreSQL,ATTR_EMULATE_PREPARES会影响PDO异常

时间:2014-11-04 14:53:33

标签: php postgresql pdo

我试图强制PDO在绑定变量的数量大于查询中的params数时抛出异常。我不喜欢使用原生的准备陈述。

如果我使用模拟的准备(PDO::ATTR_EMULATE_PREPARES => true),异常工作正常,我使用此代码测试:

$Pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$sql = 'SELECT id
        FROM my_table
        WHERE
            doc = :doc';

try {
    $Ps = $Pdo->prepare($sql, array(PDO::ATTR_EMULATE_PREPARES => true));

    $result = $Ps->execute(array(
        ':doc'  => '1234',
        ':name' => 'Myself'
    ));

} catch (PDOException $e) {
    throw new \Exception('Query failed: ' . $e->getMessage());
}

抛出:

Fatal error:  Uncaught exception 'Exception' with message 'Query failed: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens'

但如果我将PDO::ATTR_EMULATE_PREPARES更改为false,则不会抛出异常,我只会在false中收到$result。出于安全原因,我也想在这种情况下强制例外,但我没有看到如何达到这一点。欢迎任何建议。

编辑1

使用PDO::ATTR_EMULATE_PREPARES => false,如果我执行var_dump($Ps->errorInfo())我得到:

array(3) {
  [0]=>
  string(5) "HY093"
  [1]=>
  int(7)
  [2]=>
  string(0) ""
}

1 个答案:

答案 0 :(得分:2)

首先,如果我们尝试执行一个超出参数的预准备语句,PostgreSQL本身就会出错。

psql演示:

test=> prepare p as select 1+$1;
PREPARE
test=> execute p(1);
 ?column? 
----------
        2
(1 row)
test=> execute p(1,2);
ERROR:  wrong number of parameters for prepared statement "p"
DETAIL:  Expected 1 parameters but got 2.

当使用带有真实预处理语句的PHP / PDO时,即使在将查询传递给postgres之前,PDO层本身也应该出错(准备是延迟的,在另一个问题中提到了更多细节:PHP Postgres PDO driver does not support prepared statement?

使用PHP 5.3.10-1ubuntu3.15,PG 9.1(Ubuntu 12.04)进行演示

<?
$pdo = new PDO('pgsql:dbname=test');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$query = "SELECT 1+:foo";

try {
  $stmt = $pdo->prepare($query);
  $stmt->execute(array(":foo"=>1  ,":other"=>2));
  var_dump($stmt->fetchAll());
}
catch(PDOException $e){
  echo "Error ".  $e->getMessage() ."\n";
} 
?>

这会产生:

  

错误SQLSTATE [HY093]:参数号无效::其他

作为比较点,用

进行相同的测试
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

(模拟的预准备语句)产生错误,并带有不同的错误消息,问题中提到的错误消息:

  

错误SQLSTATE [HY093]:参数号无效:绑定数   变量与令牌数量不匹配

确保您使用的是最新版本的PHP / PDO。