Issue #1831184 by sun, chx: Fixed DatabaseExceptionWrapper completely hides *unexpected* errors.

8.0.x
catch 2013-01-02 11:53:49 +00:00
parent c96966f079
commit 8b1a049654
5 changed files with 68 additions and 11 deletions

View File

@ -478,9 +478,9 @@ abstract class Connection extends PDO {
* @param $query
* The query to execute. In most cases this will be a string containing
* an SQL query with placeholders. An already-prepared instance of
* DatabaseStatementInterface may also be passed in order to allow calling
* StatementInterface may also be passed in order to allow calling
* code to manually bind variables to a query. If a
* DatabaseStatementInterface is passed, the $args array will be ignored.
* StatementInterface is passed, the $args array will be ignored.
* It is extremely rare that module code will need to pass a statement
* object to this method. It is used primarily for database drivers for
* databases that require special LOB field handling.
@ -492,7 +492,7 @@ abstract class Connection extends PDO {
* An associative array of options to control how the query is run. See
* the documentation for DatabaseConnection::defaultOptions() for details.
*
* @return Drupal\Core\Database\StatementInterface
* @return \Drupal\Core\Database\StatementInterface
* This method will return one of: the executed statement, the number of
* rows affected by the query (not the number matched), or the generated
* insert ID of the last query, depending on the value of
@ -502,7 +502,7 @@ abstract class Connection extends PDO {
* $options['throw_exception'] is TRUE.
*
* @throws PDOException
* @throws Drupal\Core\Database\IntegrityConstraintViolationException
* @throws \Drupal\Core\Database\IntegrityConstraintViolationException
*/
public function query($query, array $args = array(), $options = array()) {
@ -513,7 +513,7 @@ abstract class Connection extends PDO {
// We allow either a pre-bound statement object or a literal string.
// In either case, we want to end up with an executed statement object,
// which we pass to PDOStatement::execute.
if ($query instanceof DatabaseStatementInterface) {
if ($query instanceof StatementInterface) {
$stmt = $query;
$stmt->execute(NULL, $options);
}
@ -544,7 +544,7 @@ abstract class Connection extends PDO {
// Wrap the exception in another exception, because PHP does not allow
// overriding Exception::getMessage(). Its message is the extra database
// debug information.
$query_string = ($query instanceof DatabaseStatementInterface) ? $stmt->getQueryString() : $query;
$query_string = ($query instanceof StatementInterface) ? $stmt->getQueryString() : $query;
$message = $e->getMessage() . ": " . $query_string . "; " . print_r($args, TRUE);
// Match all SQLSTATE 23xxx errors.
if (substr($e->getCode(), -6, -3) == '23') {

View File

@ -11,7 +11,7 @@ use PDO;
use PDOStatement;
/**
* Default implementation of DatabaseStatementInterface.
* Default implementation of StatementInterface.
*
* PDO allows us to extend the PDOStatement class to provide additional
* functionality beyond that offered by default. We do need extra
@ -32,7 +32,7 @@ class Statement extends PDOStatement implements StatementInterface {
*/
public $dbh;
protected function __construct($dbh) {
protected function __construct(Connection $dbh) {
$this->dbh = $dbh;
$this->setFetchMode(PDO::FETCH_OBJ);
}

View File

@ -30,6 +30,25 @@ use Traversable;
*/
interface StatementInterface extends Traversable {
/**
* Constructs a new PDOStatement object.
*
* The PDO manual does not document this constructor, but when overriding the
* PDOStatement class with a custom without this constructor, PDO will throw
* the internal exception/warning:
*
* "PDO::query(): SQLSTATE[HY000]: General error: user-supplied statement does
* not accept constructor arguments"
*
* PDO enforces that the access type of this constructor must be protected,
* and lastly, it also enforces that a custom PDOStatement interface (like
* this) omits the constructor (declaring it results in fatal errors
* complaining about "the access type must not be public" if it is public, and
* "the access type must be omitted" if it is protected; i.e., conflicting
* statements). The access type has to be protected.
*/
//protected function __construct(Connection $dbh);
/**
* Executes a prepared statement
*
@ -113,7 +132,7 @@ interface StatementInterface extends Traversable {
/**
* Fetches the next row and returns it as an object.
*
* The object will be of the class specified by DatabaseStatementInterface::setFetchMode()
* The object will be of the class specified by StatementInterface::setFetchMode()
* or stdClass if not specified.
*/
// public function fetchObject();

View File

@ -13,7 +13,7 @@ use PDO;
use PDOException;
/**
* An implementation of DatabaseStatementInterface that prefetches all data.
* An implementation of StatementInterface that prefetches all data.
*
* This class behaves very similar to a PDOStatement but as it always fetches
* every row it is possible to manipulate those results.
@ -342,7 +342,7 @@ class StatementPrefetch implements Iterator, StatementInterface {
return isset($this->currentRow);
}
/* Implementations of DatabaseStatementInterface. */
/* Implementations of StatementInterface. */
public function rowCount() {
return $this->rowCount;

View File

@ -0,0 +1,38 @@
<?php
/**
* @file
* Contains Drupal\system\Tests\Database\DatabaseExceptionWrapperTest.
*/
namespace Drupal\system\Tests\Database;
use Drupal\Core\Database\DatabaseExceptionWrapper;
use Drupal\Core\Database\Database;
use Drupal\simpletest\UnitTestBase;
/**
* Tests DatabaseExceptionWrapper thrown.
*/
class DatabaseExceptionWrapperTest extends UnitTestBase {
public static function getInfo() {
return array(
'name' => 'Database exceptiontests',
'description' => 'Tests exceptions thrown by queries.',
'group' => 'Database',
);
}
function testDatabaseExceptionWrapper() {
$connection = Database::getConnection();
$query = $connection->prepare('bananas');
try {
$connection->query($query);
$this->fail('The expected exception is not thrown.');
}
catch (DatabaseExceptionWrapper $e) {
$this->pass('The expected exception has been thrown.');
}
}
}