diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php index 234af008734a0f2dad055f1ee2c44094fc83b535..51efaf46bf08f8e9b95509a73f56ddaaf42d54f6 100644 --- a/core/lib/Drupal/Core/Database/Connection.php +++ b/core/lib/Drupal/Core/Database/Connection.php @@ -478,9 +478,9 @@ protected function filterComment($comment = '') { * @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 @@ protected function filterComment($comment = '') { * 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 @@ protected function filterComment($comment = '') { * $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 @@ public function query($query, array $args = array(), $options = array()) { // 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 @@ public function query($query, array $args = array(), $options = array()) { // 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') { diff --git a/core/lib/Drupal/Core/Database/Statement.php b/core/lib/Drupal/Core/Database/Statement.php index c5b1735e33c876b7f9b3ca236456089e45be5b1e..120fac6c1c7d6d86515e944a01391ba10ae0afd9 100644 --- a/core/lib/Drupal/Core/Database/Statement.php +++ b/core/lib/Drupal/Core/Database/Statement.php @@ -11,7 +11,7 @@ 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); } diff --git a/core/lib/Drupal/Core/Database/StatementInterface.php b/core/lib/Drupal/Core/Database/StatementInterface.php index 7f1ca4a09172da3d71c6f4e55b0f882b783d9004..b3d356c57407bb2e3fd7d39b0bc8674c39d8cca3 100644 --- a/core/lib/Drupal/Core/Database/StatementInterface.php +++ b/core/lib/Drupal/Core/Database/StatementInterface.php @@ -30,6 +30,25 @@ */ 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 @@ public function fetchField($index = 0); /** * 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(); diff --git a/core/lib/Drupal/Core/Database/StatementPrefetch.php b/core/lib/Drupal/Core/Database/StatementPrefetch.php index 18dd5826a66a0c61a47ecc1480971619317d8ba8..e01f03adafc2617a2a039449e2c45c880a1b4fb9 100644 --- a/core/lib/Drupal/Core/Database/StatementPrefetch.php +++ b/core/lib/Drupal/Core/Database/StatementPrefetch.php @@ -13,7 +13,7 @@ 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 @@ public function valid() { return isset($this->currentRow); } - /* Implementations of DatabaseStatementInterface. */ + /* Implementations of StatementInterface. */ public function rowCount() { return $this->rowCount; diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/DatabaseExceptionWrapperTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/DatabaseExceptionWrapperTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9d34e9ac6c78cd09e4a3f2ab26df3738b8110020 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Database/DatabaseExceptionWrapperTest.php @@ -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.'); + } + } + +}