php - new - pdo query
El controlador PHP Postgres PDO no es compatible con la instrucción preparada? (1)
Ver http://www.php.net/manual/en/pdo.prepare.php
Nota:
Las declaraciones preparadas emuladas no se comunican con el servidor de la base de datos, por lo que PDO :: prepare () no verifica la declaración.
(de hecho, las declaraciones realmente preparadas no se envían inmediatamente de todos modos, ver la respuesta a la Q2 a continuación)
De todos modos, puedes emitir:
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
para obtener sentencias preparadas reales implementadas con el comando SQL PREPARE. Ver http://www.php.net/manual/en/pdo.setattribute.php para más.
En discusiones y pruebas adicionales, surgen dos preguntas:
Q1. ¿Por qué pdo::getAttribute(PDO::ATTR_EMULATE_PREPARES)
produce un error?
De hecho, setAttribute
no tiene errores, pero getAttribute(PDO::ATTR_EMULATE_PREPARES)
dice:
''SQLSTATE [IM001]: el controlador no admite esta función: el controlador no admite ese atributo''
En cuanto a la documentación para pdo :: getAttribute , dice Las constantes que se aplican a las conexiones de la base de datos son las siguientes , y una serie de constantes se siguen de PDO::ATTR_AUTOCOMMIT
a PDO::ATTR_TIMEOUT
, y es notable que PDO::ATTR_EMULATE_PREPARES
no es en ellos Así que estrictamente hablando, no deberíamos esperar que getAttribute(PDO::ATTR_EMULATE_PREPARES)
funcione de todos modos.
Ahora, mirando el código fuente para estar seguro, parece que el controlador pdo_pgsql
proporciona una función pdo_pgsql_get_attribute
que tiene una instrucción switch pdo_pgsql_get_attribute
:
- PDO_ATTR_CLIENT_VERSION
- PDO_ATTR_SERVER_VERSION
- PDO_ATTR_CONNECTION_STATUS
- PDO_ATTR_SERVER_INFO
y eso es. No hay rastro de PDO_ATTR_EMULATE_PREPARES por lo que en última instancia aparece este error.
Por otro lado, la función pdo_pgsql_set_attr
tiene una instrucción switch pdo_pgsql_set_attr
:
- PDO_ATTR_EMULATE_PREPARES
- PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT
que confirma que este atributo se tiene realmente en cuenta cuando se establece. Entonces PDO es simplemente inconsistente con getAttribute
que no coincide con setAttribute
.
P2: cuando la emulación de preparación es falsa, ¿por qué una afirmación falsa no provoca un error inmediatamente cuando está preparada?
Considere este fragmento de código en 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);
Muestra que se usa PQprepare
(por lo que es una declaración preparada "real"), pero también que la declaración no se envía inmediatamente al servidor. Es por eso que dbo::prepare("bogus statement")
no devolverá falso: en realidad no se envía al servidor por falta de tipos de parámetros.
¿Me estoy volviendo loco o el driver Postgres PDO simplemente no admite declaraciones preparadas, sino que emula el lado del cliente?
El siguiente código devuelve NO ERROR para la llamada a prepare (), aunque debería. En cambio, devuelve el error aplicable cuando se ejecuta execute ().
Editar: Como según Daniel Vérité estoy equivocado, agregué su código sugerido. Aún tengo el error. Mi código ahora se ve como el de abajo, con la línea de Daniel añadida.
<?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 versión 5.3.15, PHP Postgres cliente versión 9.1.4, servidor de Postgres versión 9.2.1.