Obtener una cadena de consulta SQL sin formato a partir de declaraciones preparadas por PDO

Resuelto Wilco asked hace 54 años • 16 respuestas

¿Hay alguna manera de ejecutar la cadena SQL sin formato al llamar a PDOStatement::execute() en una declaración preparada? Para fines de depuración, esto sería extremadamente útil.

Wilco avatar Jan 01 '70 08:01 Wilco
Aceptado

Supongo que quiere decir que desea la consulta SQL final, con los valores de los parámetros interpolados en ella. Entiendo que esto sería útil para la depuración, pero no es la forma en que funcionan las declaraciones preparadas. Los parámetros no se combinan con una declaración preparada en el lado del cliente, por lo que PDO nunca debería tener acceso a la cadena de consulta combinada con sus parámetros.

La declaración SQL se envía al servidor de la base de datos cuando prepara () y los parámetros se envían por separado cuando ejecuta (). El registro de consultas generales de MySQL muestra el SQL final con valores interpolados después de ejecutar(). A continuación se muestra un extracto de mi registro de consultas generales. Ejecuté las consultas desde la CLI de mysql, no desde PDO, pero el principio es el mismo.

081016 16:51:28 2 Query       prepare s1 from 'select * from foo where i = ?'
                2 Prepare     [2] select * from foo where i = ?
081016 16:51:39 2 Query       set @a =1
081016 16:51:47 2 Query       execute s1 using @a
                2 Execute     [2] select * from foo where i = 1

También puede obtener lo que desea si configura el atributo PDO PDO::ATTR_EMULATE_PREPARES. En este modo, PDO interpola parámetros en la consulta SQL y envía la consulta completa cuando ejecuta(). Esta no es una verdadera consulta preparada. Evitará los beneficios de las consultas preparadas interpolando variables en la cadena SQL antes de ejecutar().


Re comentario de @afilina:

No, la consulta SQL textual no se combina con los parámetros durante la ejecución. Así que PDO no tiene nada que mostrarle.

Internamente, si usa PDO::ATTR_EMULATE_PREPARES, PDO hace una copia de la consulta SQL e interpola los valores de los parámetros en ella antes de preparar y ejecutar. Pero PDO no expone esta consulta SQL modificada.

El objeto PDOStatement tiene una propiedad $queryString, pero se establece solo en el constructor de PDOStatement y no se actualiza cuando la consulta se reescribe con parámetros.

Sería una solicitud de función razonable para PDO pedirles que expongan la consulta reescrita. Pero incluso eso no le daría la consulta "completa" a menos que use PDO::ATTR_EMULATE_PREPARES.

Es por eso que muestro la solución anterior de usar el registro de consultas generales del servidor MySQL, porque en este caso incluso una consulta preparada con marcadores de posición de parámetros se reescribe en el servidor, con los valores de los parámetros rellenados en la cadena de consulta. Pero esto sólo se hace durante el registro, no durante la ejecución de la consulta.

Bill Karwin avatar Oct 16 '2008 23:10 Bill Karwin
/**
 * Replaces any parameter placeholders in a query with the value of that
 * parameter. Useful for debugging. Assumes anonymous parameters from 
 * $params are are in the same order as specified in $query
 *
 * @param string $query The sql query with parameter placeholders
 * @param array $params The array of substitution parameters
 * @return string The interpolated query
 */
public static function interpolateQuery($query, $params) {
    $keys = array();

    # build a regular expression for each parameter
    foreach ($params as $key => $value) {
        if (is_string($key)) {
            $keys[] = '/:'.$key.'/';
        } else {
            $keys[] = '/[?]/';
        }
    }

    $query = preg_replace($keys, $params, $query, 1, $count);

    #trigger_error('replaced '.$count.' keys');

    return $query;
}
bigwebguy avatar Sep 04 '2009 01:09 bigwebguy