* @author Jarno Rantanen * @since 2007-07-12 * @package propel.runtime.connection */ class DebugPDOStatement extends PDOStatement { /** * The PDO connection from which this instance was created. * * @var PropelPDO */ protected $pdo; /** * Hashmap for resolving the PDO::PARAM_* class constants to their human-readable names. * * This is only used in logging the binding of variables. * * @see self::bindValue() * @var array */ protected static $typeMap = array( PDO::PARAM_BOOL => "PDO::PARAM_BOOL", PDO::PARAM_INT => "PDO::PARAM_INT", PDO::PARAM_STR => "PDO::PARAM_STR", PDO::PARAM_LOB => "PDO::PARAM_LOB", PDO::PARAM_NULL => "PDO::PARAM_NULL", ); /** * @var array The values that have been bound */ protected $boundValues = array(); /** * Construct a new statement class with reference to main DebugPDO object from * which this instance was created. * * @param DebugPDO $pdo Reference to the parent PDO instance. */ protected function __construct(PropelPDO $pdo) { $this->pdo = $pdo; } public function getExecutedQueryString() { $sql = $this->queryString; $matches = array(); if (preg_match_all('/(:p[0-9]+\b)/', $sql, $matches)) { $size = count($matches[1]); for ($i = $size-1; $i >= 0; $i--) { $pos = $matches[1][$i]; $sql = str_replace($pos, $this->boundValues[$pos], $sql); } } return $sql; } /** * Executes a prepared statement. Returns a boolean value indicating success. * * Overridden for query counting and logging. * * @return bool */ public function execute($input_parameters = null) { $debug = $this->pdo->getDebugSnapshot(); $return = parent::execute($input_parameters); $sql = $this->getExecutedQueryString(); $this->pdo->log($sql, null, __METHOD__, $debug); $this->pdo->setLastExecutedQuery($sql); $this->pdo->incrementQueryCount(); return $return; } /** * Binds a value to a corresponding named or question mark placeholder in the SQL statement * that was use to prepare the statement. Returns a boolean value indicating success. * * @param int $pos Parameter identifier (for determining what to replace in the query). * @param mixed $value The value to bind to the parameter. * @param int $type Explicit data type for the parameter using the PDO::PARAM_* constants. Defaults to PDO::PARAM_STR. * @return boolean */ public function bindValue($pos, $value, $type = PDO::PARAM_STR) { $debug = $this->pdo->getDebugSnapshot(); $typestr = isset(self::$typeMap[$type]) ? self::$typeMap[$type] : '(default)'; $return = parent::bindValue($pos, $value, $type); $valuestr = $type == PDO::PARAM_LOB ? '[LOB value]' : var_export($value, true); $msg = sprintf('Binding %s at position %s w/ PDO type %s', $valuestr, $pos, $typestr); $this->boundValues[$pos] = $valuestr; $this->pdo->log($msg, null, __METHOD__, $debug); return $return; } /** * Binds a PHP variable to a corresponding named or question mark placeholder in the SQL statement * that was use to prepare the statement. Unlike PDOStatement::bindValue(), the variable is bound * as a reference and will only be evaluated at the time that PDOStatement::execute() is called. * Returns a boolean value indicating success. * * @param int $pos Parameter identifier (for determining what to replace in the query). * @param mixed $value The value to bind to the parameter. * @param int $type Explicit data type for the parameter using the PDO::PARAM_* constants. Defaults to PDO::PARAM_STR. * @param int $length Length of the data type. To indicate that a parameter is an OUT parameter from a stored procedure, you must explicitly set the length. * @return boolean */ public function bindParam($pos, &$value, $type = PDO::PARAM_STR, $length = 0, $driver_options = null) { $debug = $this->pdo->getDebugSnapshot(); $typestr = isset(self::$typeMap[$type]) ? self::$typeMap[$type] : '(default)'; $return = parent::bindParam($pos, $value, $type, $length, $driver_options); $valuestr = $length > 100 ? '[Large value]' : var_export($value, true); $msg = sprintf('Binding %s at position %s w/ PDO type %s', $valuestr, $pos, $typestr); $this->boundValues[$pos] = $valuestr; $this->pdo->log($msg, null, __METHOD__, $debug); return $return; } }