Skip to content

Commit

Permalink
Throw OptimisticLockException when connection::commit() returns false
Browse files Browse the repository at this point in the history
  • Loading branch information
chosroes committed Dec 19, 2019
1 parent a416a9a commit 3418aac
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .scrutinizer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ build:
analysis:
environment:
php:
version: 7.1
version: 7.2
cache:
disabled: false
directories:
Expand Down
11 changes: 0 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ sudo: false
language: php

php:
- 7.1
- 7.2
- 7.3
- 7.4snapshot
Expand Down Expand Up @@ -32,16 +31,6 @@ jobs:
addons:
mariadb: 10.1

- stage: Test
dist: xenial
env: DB=mysql MYSQL_VERSION=5.7
php: 7.1
services:
- mysql
before_script:
- ./tests/travis/install-mysql-$MYSQL_VERSION.sh
sudo: required

- stage: Test
dist: xenial
env: DB=mysql MYSQL_VERSION=5.7
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
"sort-packages": true
},
"require": {
"php": "^7.1",
"php": "^7.2",
"ext-pdo": "*",
"doctrine/annotations": "^1.8",
"doctrine/cache": "^1.9.1",
"doctrine/collections": "^1.5",
"doctrine/common": "^2.11",
"doctrine/dbal": "^2.9.3",
"doctrine/dbal": "^2.10.0",
"doctrine/event-manager": "^1.1",
"doctrine/instantiator": "^1.3",
"doctrine/persistence": "^1.2",
Expand Down
48 changes: 29 additions & 19 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions lib/Doctrine/ORM/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,18 @@ public function commit($entity = null)
}
}

$conn->commit();
// Commit failed silently
if ( ! $conn->commit()) {
$object = is_object($entity) ? $entity : null;

throw new OptimisticLockException('Commit failed', $object);
}
} catch (Throwable $e) {
$this->em->close();
$conn->rollBack();

if ($conn->isTransactionActive()) {
$conn->rollBack();
}

$this->afterTransactionRolledBack();

Expand Down
22 changes: 22 additions & 0 deletions tests/Doctrine/Tests/Mocks/ConnectionCommitFailMock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Doctrine\Tests\Mocks;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Statement;

/**
* Mock class for Connection.
*/
class ConnectionCommitFailMock extends ConnectionMock
{
/**
* Return false to raise an error
*
* @return bool
*/
public function commit()
{
return false;
}
}
30 changes: 29 additions & 1 deletion tests/Doctrine/Tests/ORM/UnitOfWorkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
use Doctrine\Common\PropertyChangedListener;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMInvalidArgumentException;
use Doctrine\ORM\UnitOfWork;
use Doctrine\Tests\Mocks\ConnectionCommitFailMock;
use Doctrine\Tests\Mocks\ConnectionMock;
use Doctrine\Tests\Mocks\DriverMock;
use Doctrine\Tests\Mocks\EntityManagerMock;
Expand Down Expand Up @@ -277,7 +279,7 @@ public function testNoUndefinedIndexNoticeOnScheduleForUpdateWithoutChanges()

// Create a test user
$user = new ForumUser();
$user->name = 'Jasper';
$user->username = 'Jasper';
$this->_unitOfWork->persist($user);
$this->_unitOfWork->commit();

Expand Down Expand Up @@ -789,6 +791,32 @@ public function testPreviousDetectedIllegalNewNonCascadedEntitiesAreCleanedUpOnS
self::assertCount(1, $persister1->getInserts());
self::assertCount(0, $persister2->getInserts());
}

/**
* @group #7946 Throw OptimisticLockException when connection::commit() returns false.
*/
public function testCommitThrowOptimisticLockExceptionWhenConnectionCommitReturnFalse(): void
{
// Set another connection mock that fail on commit
$this->_connectionMock = new ConnectionCommitFailMock([], new DriverMock());
$this->eventManager = $this->getMockBuilder(EventManager::class)->getMock();
$this->_emMock = EntityManagerMock::create($this->_connectionMock, null, $this->eventManager);
$this->_unitOfWork = new UnitOfWorkMock($this->_emMock);
$this->_emMock->setUnitOfWork($this->_unitOfWork);

// Setup fake persister and id generator
$userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata(ForumUser::class));
$userPersister->setMockIdGeneratorType(ClassMetadata::GENERATOR_TYPE_IDENTITY);
$this->_unitOfWork->setEntityPersister(ForumUser::class, $userPersister);

// Create a test user
$user = new ForumUser();
$user->username = 'Jasper';
$this->_unitOfWork->persist($user);

$this->expectException(OptimisticLockException::class);
$this->_unitOfWork->commit();
}
}

/**
Expand Down

0 comments on commit 3418aac

Please sign in to comment.