diff --git a/includes/common.inc b/includes/common.inc index 26282bf5b1a..e110e517aa9 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -729,6 +729,8 @@ function _drupal_exception_handler($exception) { * @return An error in the format expected by _drupal_log_error(). */ function _drupal_decode_exception($exception) { + $message = $exception->getMessage(); + $backtrace = $exception->getTrace(); // Add the line throwing the exception to the backtrace. array_unshift($backtrace, array('line' => $exception->getLine(), 'file' => $exception->getFile())); @@ -741,17 +743,20 @@ function _drupal_decode_exception($exception) { // or in one of its global functions. $db_functions = array('db_query', 'pager_query', 'db_query_range', 'db_query_temporary', 'update_sql'); while (!empty($backtrace[1]) && ($caller = $backtrace[1]) && - ((isset($caller['class']) && (strpos($caller['class'], 'Query') !== FALSE || strpos($caller['class'], 'Database') !== FALSE)) || + ((isset($caller['class']) && (strpos($caller['class'], 'Query') !== FALSE || strpos($caller['class'], 'Database') !== FALSE || $caller['class'] == 'PDOStatement')) || in_array($caller['function'], $db_functions))) { // We remove that call. array_shift($backtrace); } + if (isset($exception->query_string, $exception->args)) { + $message .= ": " . $exception->query_string . "; " . print_r($exception->args, TRUE); + } } $caller = _drupal_get_last_caller($backtrace); return array( '%type' => get_class($exception), - '%message' => $exception->getMessage(), + '%message' => $message, '%function' => $caller['function'], '%file' => $caller['file'], '%line' => $caller['line'], diff --git a/includes/database/database.inc b/includes/database/database.inc index 60d4b415fae..f1185c77aca 100644 --- a/includes/database/database.inc +++ b/includes/database/database.inc @@ -595,13 +595,15 @@ abstract class DatabaseConnection extends PDO { catch (PDOException $e) { _db_check_install_needed(); if ($options['throw_exception']) { + // Add additional debug information. if ($query instanceof DatabaseStatementInterface) { - $query_string = $stmt->getQueryString(); + $e->query_string = $stmt->getQueryString(); } else { - $query_string = $query; + $e->query_string = $query; } - throw new PDOException($query_string . " - \n" . print_r($args, 1) . $e->getMessage()); + $e->args = $args; + throw $e; } return NULL; } diff --git a/includes/database/pgsql/database.inc b/includes/database/pgsql/database.inc index ba82aa0b0fc..0f5627c2a28 100644 --- a/includes/database/pgsql/database.inc +++ b/includes/database/pgsql/database.inc @@ -80,13 +80,15 @@ class DatabaseConnection_pgsql extends DatabaseConnection { catch (PDOException $e) { _db_check_install_needed(); if ($options['throw_exception']) { + // Add additional debug information. if ($query instanceof DatabaseStatementInterface) { - $query_string = $stmt->getQueryString(); + $e->query_string = $stmt->getQueryString(); } else { - $query_string = $query; + $e->query_string = $query; } - throw new PDOException($query_string . " - \n" . print_r($args, 1) . $e->getMessage()); + $e->args = $args; + throw $e; } return NULL; } diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test index 0263036ef25..e5d5b3fe0b1 100644 --- a/modules/simpletest/tests/database_test.test +++ b/modules/simpletest/tests/database_test.test @@ -2446,6 +2446,9 @@ class DatabaseInvalidDataTestCase extends DatabaseTestCase { $this->pass(t('The whole transaction is rolled back when a duplicate key insert occurs.')); } + // 23000 means "Integrity constraint violation" according to ANSI SQL. + $this->assertEqual($e->errorInfo[0], '23000', t('Exception has proper SQLSTATE.')); + // Ensure the other values were not inserted. $record = db_select('test') ->fields('test', array('name', 'age')) diff --git a/modules/simpletest/tests/error.test b/modules/simpletest/tests/error.test index 8584e2a40a2..ed430bfff26 100644 --- a/modules/simpletest/tests/error.test +++ b/modules/simpletest/tests/error.test @@ -78,7 +78,7 @@ class DrupalErrorHandlerUnitTest extends DrupalWebTestCase { ); $error_pdo_exception = array( '%type' => 'PDOException', - '%message' => 'SQLSTATE', + '%message' => 'SELECT * FROM bananas_are_awesome', '%function' => 'error_test_trigger_pdo_exception()', '%line' => 65, '%file' => realpath('modules/simpletest/tests/error_test.module'), @@ -89,7 +89,7 @@ class DrupalErrorHandlerUnitTest extends DrupalWebTestCase { $this->drupalGet('error-test/trigger-pdo-exception'); // We cannot use assertErrorMessage() since the extact error reported - // varies from database to database. Check for the error keyword 'SQLSTATE'. + // varies from database to database. Check that the SQL string is displayed. $this->assertText($error_pdo_exception['%type'], t('Found %type in error page.', $error_pdo_exception)); $this->assertText($error_pdo_exception['%message'], t('Found %message in error page.', $error_pdo_exception)); $error_details = t('in %function (line %line of %file)', $error_pdo_exception);