diff --git a/common/framework/helpers/dbhelper.php b/common/framework/helpers/dbhelper.php index 72c26702f..100f9e701 100644 --- a/common/framework/helpers/dbhelper.php +++ b/common/framework/helpers/dbhelper.php @@ -8,6 +8,9 @@ use Rhymix\Framework\Exceptions\DBError; /** * DB helper class. + * + * We use instances of this class instead of raw PDO in order to provide + * better logging and error handling while keeping backward compatibility. */ class DBHelper extends \PDO { @@ -38,23 +41,32 @@ class DBHelper extends \PDO try { - if ($driver_options) - { - $stmt = parent::prepare($statement, $driver_options); - } - else - { - $stmt = parent::prepare($statement); - } + /** + * $stmt will be an instance of DBStmtHelper. + * This allows it to track the parent database's type + * and send query logs to the appropriate place. + */ + $stmt = $driver_options ? parent::prepare($statement, $driver_options) : parent::prepare($statement); $stmt->setFetchMode(\PDO::FETCH_OBJ); $stmt->setType($this->_type); + $db_class->clearError(); } catch (\PDOException $e) { + /** + * We only measure the time when the prepared statement fails. + * If the statement is successfully prepared, time will be measured + * when the statement is executed in DBStmtHelper. + */ $elapsed_time = microtime(true) - $start_time; $db_class->addElapsedTime($elapsed_time); $db_class->setError(-1, $e->getMessage()); Debug::addQuery($db_class->getQueryLog($statement, $elapsed_time)); + + /** + * This is a new feature in Rhymix 2.0 so we don't have to mess + * with status objects. We just throw an exception. Catch it! + */ throw new DBError($e->getMessage(), 0, $e); } @@ -64,6 +76,10 @@ class DBHelper extends \PDO /** * Execute a query. * + * This method accepts additional parameters, but they are not for creating + * prepared statements. They exist because PDO's own query() method accepts + * various kinds of additional parameters, and we don't want to touch them. + * * @param string $statement * @return PDOStatement|DBStmtHelper */ @@ -76,6 +92,11 @@ class DBHelper extends \PDO try { + /** + * $stmt will be an instance of DBStmtHelper. + * This allows it to track the parent database's type + * and send query logs to the appropriate place. + */ $stmt = parent::query($statement, ...$args); $stmt->setFetchMode(\PDO::FETCH_OBJ); $stmt->setType($this->_type); @@ -85,10 +106,12 @@ class DBHelper extends \PDO { $db_class->setError(-1, $e->getMessage()); } - - $elapsed_time = microtime(true) - $start_time; - $db_class->addElapsedTime($elapsed_time); - Debug::addQuery($db_class->getQueryLog($statement, $elapsed_time)); + finally + { + $elapsed_time = microtime(true) - $start_time; + $db_class->addElapsedTime($elapsed_time); + Debug::addQuery($db_class->getQueryLog($statement, $elapsed_time)); + } return $stmt; } @@ -113,10 +136,12 @@ class DBHelper extends \PDO { $db_class->setError(-1, $e->getMessage()); } - - $elapsed_time = microtime(true) - $start_time; - $db_class->addElapsedTime($elapsed_time); - Debug::addQuery($db_class->getQueryLog($query, $elapsed_time)); + finally + { + $elapsed_time = microtime(true) - $start_time; + $db_class->addElapsedTime($elapsed_time); + Debug::addQuery($db_class->getQueryLog($query, $elapsed_time)); + } return $result; } diff --git a/common/framework/helpers/dbstmthelper.php b/common/framework/helpers/dbstmthelper.php index 7496e8cb2..97adfccd0 100644 --- a/common/framework/helpers/dbstmthelper.php +++ b/common/framework/helpers/dbstmthelper.php @@ -8,6 +8,10 @@ use Rhymix\Framework\Exceptions\DBError; /** * DB Statement helper class. + * + * We use instances of this class instead of raw PDOStatement in order to log + * individual execute() calls of prepared statements. This is controlled by + * the PDO::ATTR_STATEMENT_CLASS attribute set in the DB class. */ class DBStmtHelper extends \PDOStatement { @@ -27,6 +31,10 @@ class DBStmtHelper extends \PDOStatement /** * Execute a prepared statement. * + * We don't set a type for $input_parameters because the original + * PDOStatement class accepts both arrays and null. Actually, the null + * value must be omitted altogether or it will throw an error. + * * @param array $input_parameters * @return bool */ @@ -39,19 +47,17 @@ class DBStmtHelper extends \PDOStatement { $result = parent::execute($input_parameters); $db_class->clearError(); - - $elapsed_time = microtime(true) - $start_time; - $db_class->addElapsedTime($elapsed_time); - Debug::addQuery($db_class->getQueryLog($this->queryString, $elapsed_time)); } catch (\PDOException $e) { $db_class->setError(-1, $e->getMessage()); - + throw new DBError($e->getMessage(), 0, $e); + } + finally + { $elapsed_time = microtime(true) - $start_time; $db_class->addElapsedTime($elapsed_time); Debug::addQuery($db_class->getQueryLog($this->queryString, $elapsed_time)); - throw new DBError($e->getMessage(), 0, $e); } return $result;