diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index 6ad94ef93595..436a2deba015 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -7,7 +7,6 @@ use Exception; use Throwable; use LogicException; -use RuntimeException; use DateTimeInterface; use Illuminate\Support\Arr; use Illuminate\Database\Query\Expression; @@ -985,14 +984,10 @@ public function getReadPdo() * * @param \PDO|null $pdo * @return $this - * - * @throws \RuntimeException */ public function setPdo($pdo) { - if ($this->transactions >= 1) { - throw new RuntimeException("Can't swap PDO instance while within transaction."); - } + $this->transactions = 0; $this->pdo = $pdo; diff --git a/tests/Database/DatabaseConnectionTest.php b/tests/Database/DatabaseConnectionTest.php index bb40bdfe4012..bf99971b1c9f 100755 --- a/tests/Database/DatabaseConnectionTest.php +++ b/tests/Database/DatabaseConnectionTest.php @@ -156,14 +156,14 @@ public function testBeginTransactionMethodNeverRetriesIfWithinTransaction() } } - public function testCantSwapPDOWithOpenTransaction() + public function testSwapPDOWithOpenTransactionResetsTransactionLevel() { $pdo = $this->createMock('DatabaseConnectionTestMockPDO'); $pdo->expects($this->once())->method('beginTransaction')->will($this->returnValue(true)); $connection = $this->getMockConnection([], $pdo); $connection->beginTransaction(); - $this->setExpectedException('RuntimeException', "Can't swap PDO instance while within transaction."); $connection->disconnect(); + $this->assertEquals(0, $connection->transactionLevel()); } public function testBeganTransactionFiresEventsIfSet() @@ -240,24 +240,42 @@ public function testTransactionMethodRollsbackAndThrows() } /** - * @expectedException RuntimeException + * @expectedException \Illuminate\Database\QueryException */ - public function testTransactionMethodDisallowPDOChanging() + public function testOnLostConnectionPDOIsNotSwappedWithinATransaction() { - $pdo = $this->getMockBuilder('DatabaseConnectionTestMockPDO')->setMethods(['beginTransaction', 'commit', 'rollBack'])->getMock(); - $pdo->expects($this->once())->method('beginTransaction'); - $pdo->expects($this->once())->method('rollBack'); - $pdo->expects($this->never())->method('commit'); + $pdo = m::mock(PDO::class); + $pdo->shouldReceive('beginTransaction')->once(); + $statement = m::mock(PDOStatement::class); + $pdo->shouldReceive('prepare')->once()->andReturn($statement); + $statement->shouldReceive('execute')->once()->andThrow(new PDOException('server has gone away')); - $mock = $this->getMockConnection([], $pdo); + $connection = new \Illuminate\Database\Connection($pdo); + $connection->beginTransaction(); + $connection->statement('foo'); + } - $mock->setReconnector(function ($connection) { - $connection->setPDO(null); - }); + public function testOnLostConnectionPDOIsSwappedOutsideTransaction() + { + $pdo = m::mock(PDO::class); + + $statement = m::mock(PDOStatement::class); + $statement->shouldReceive('execute')->once()->andThrow(new PDOException('server has gone away')); + $statement->shouldReceive('execute')->once()->andReturn('result'); + + $pdo->shouldReceive('prepare')->twice()->andReturn($statement); - $mock->transaction(function ($connection) { - $connection->reconnect(); + $connection = new \Illuminate\Database\Connection($pdo); + + $called = false; + + $connection->setReconnector(function ($connection) use (&$called) { + $called = true; }); + + $this->assertEquals('result', $connection->statement('foo')); + + $this->assertTrue($called); } public function testRunMethodRetriesOnFailure()