PHP Postgres PDO драйвер не поддерживает подготовленный оператор?

Я схожу с ума, или драйвер Postgres PDO просто не поддерживает подготовленные операторы, а вместо этого имитирует их клиентскую сторону?

Следующий код возвращает NO ERROR для вызова prepare (), хотя он и должен. Вместо этого он возвращает применимую ошибку при вызове функции execute ().

Редактировать: Поскольку в соответствии с Даниэлем Верите я ошибаюсь, я добавил его предлагаемый код. Я все еще получаю ошибку. Теперь мой код выглядит следующим образом: добавлена ​​линия Даниила.

<?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.

См. http://www.php.net/manual/en/pdo.prepare.php

Заметка:

Эмулированные подготовленные операторы не взаимодействуют с сервером базы данных, поэтому PDO :: prepare () не проверяет инструкцию.

(на самом деле реальные подготовленные заявления не отправляются немедленно в любом случае, см. ответ на Q2 ниже)

В любом случае вы можете опубликовать:

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

для получения реальных подготовленных операторов, реализованных с помощью команды SQL PREPARE. Подробнее см. http://www.php.net/manual/en/pdo.setattribute.php .

При дальнейшем обсуждении и испытаниях возникают два вопроса:

Q1. Почему pdo::getAttribute(PDO::ATTR_EMULATE_PREPARES) дает ошибку?
Действительно setAttribute не setAttribute ошибку, но getAttribute(PDO::ATTR_EMULATE_PREPARES) говорит:

'SQLSTATE [IM001]: драйвер не поддерживает эту функцию: драйвер не поддерживает этот атрибут'

Рассматривая документацию для pdo :: getAttribute , он говорит, что константы, которые применяются к соединениям с базой данных, следующие , а ряд констант следует из PDO::ATTR_AUTOCOMMIT в PDO::ATTR_TIMEOUT , и замечательно, что PDO::ATTR_EMULATE_PREPARES не является в них . Так что, строго говоря, мы не должны ожидать, что getAttribute(PDO::ATTR_EMULATE_PREPARES) будет работать.

Теперь, смотря на исходный код, pdo_pgsql драйвер pdo_pgsql предоставляет функцию pdo_pgsql_get_attribute которая имеет оператор switch:

  • PDO_ATTR_CLIENT_VERSION
  • PDO_ATTR_SERVER_VERSION
  • PDO_ATTR_CONNECTION_STATUS
  • PDO_ATTR_SERVER_INFO

вот и все. Никаких следов PDO_ATTR_EMULATE_PREPARES, поэтому в конечном итоге появляется эта ошибка.

С другой стороны, функция pdo_pgsql_set_attr имеет оператор switch:

  • PDO_ATTR_EMULATE_PREPARES
  • PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT

что подтверждает, что этот атрибут фактически принимается во внимание при установке. Таким образом, PDO просто несовместим с getAttribute , который не соответствует setAttribute .

Q2. Когда подготовка эмуляции ложна, почему не поддельное утверждение сразу же вызывает ошибку при подготовке?

Рассмотрим этот фрагмент кода в 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: на самом деле он не отправляется на сервер из-за отсутствия типов параметров.