Я схожу с ума, или драйвер 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_EMULATE_PREPARES, поэтому в конечном итоге появляется эта ошибка.
С другой стороны, функция pdo_pgsql_set_attr
имеет оператор switch:
что подтверждает, что этот атрибут фактически принимается во внимание при установке. Таким образом, 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: на самом деле он не отправляется на сервер из-за отсутствия типов параметров.