diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php index c588dc9dfa..da77a89c76 100644 --- a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php +++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php @@ -11,6 +11,7 @@ use Drupal\Core\Database\DatabaseException; use Drupal\Core\Database\Connection as DatabaseConnection; use Drupal\Component\Utility\Unicode; +use Drupal\Core\Database\TransactionNoActiveException; /** * @addtogroup database @@ -421,35 +422,35 @@ protected function popCommittableTransactions() { * {@inheritdoc} */ public function rollBack($savepoint_name = 'drupal_transaction') { - try { - return parent::rollBack($savepoint_name); + if (!$this->inTransaction()) { + throw new TransactionNoActiveException(); } - catch (\PdoException $e) { + // A previous rollback to an earlier savepoint may mean that the savepoint + // in question has already been accidentally committed. + if (!isset($this->transactionLayers[$savepoint_name])) { + throw new TransactionNoActiveException(); } - if ($e->getMessage() === 'There is no active transaction') { + if (!$this->connection->inTransaction()) { // On PHP 7 $this->connection->rollback() does not throw an exception if // there is no active transaction. In order to maintain consistent - // behaviour on PHP 8 we have to ignore this error. This situation occurs + // behavior on PHP 8 we have to ignore this error. This situation occurs // when tables are altered or created (DDL transactions are not // supported). trigger_error('Rollback attempted when there is no active transaction. This can cause data integrity issues.', E_USER_WARNING); return; } - throw $e; + return parent::rollBack($savepoint_name); } /** * {@inheritdoc} */ protected function doCommit() { - try { + if ($this->connection->inTransaction()) { $success = parent::doCommit(); } - catch (\PdoException $e) { - if ($e->getMessage() !== 'There is no active transaction') { - throw new DatabaseExceptionWrapper($e->getMessage(), $e->getCode(), $e); - } + else { // On PHP 7 $this->connection->commit() does not throw an exception if // there is no active transaction. In order to maintain consistent // behaviour on PHP 8 we have to assume that all queries have been