diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index 49a0ccfae7e2..511f45ac1436 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -1061,6 +1061,10 @@ public function reconnectIfMissingConnection() */ public function disconnect() { + if ($this->transactions > 0) { + $this->transactionsManager?->rollback($this->getName(), 0); + } + $this->setPdo(null)->setReadPdo(null); } diff --git a/tests/Database/DatabaseConnectionTest.php b/tests/Database/DatabaseConnectionTest.php index f91806bc6a65..f9a88ddd9e91 100755 --- a/tests/Database/DatabaseConnectionTest.php +++ b/tests/Database/DatabaseConnectionTest.php @@ -7,6 +7,7 @@ use Exception; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Database\Connection; +use Illuminate\Database\DatabaseTransactionsManager; use Illuminate\Database\Events\QueryExecuted; use Illuminate\Database\Events\TransactionBeginning; use Illuminate\Database\Events\TransactionCommitted; @@ -252,6 +253,45 @@ public function testSwapPDOWithOpenTransactionResetsTransactionLevel() $this->assertEquals(0, $connection->transactionLevel()); } + public function testDisconnectRollsBackTransactionsManagerWhenTransactionIsActive() + { + $pdo = $this->createMock(DatabaseConnectionTestMockPDO::class); + $connection = $this->getMockConnection(['getName'], $pdo); + $connection->method('getName')->willReturn('name'); + $connection->setTransactionManager($manager = new DatabaseTransactionsManager); + + $connection->beginTransaction(); + + $connection->disconnect(); + + $this->assertCount(0, $manager->getPendingTransactions()); + $this->assertEquals(0, $connection->transactionLevel()); + } + + public function testDisconnectMidTransactionDiscardsStaleAfterCommitCallbacks() + { + $pdo = $this->createMock(DatabaseConnectionTestMockPDO::class); + $connection = $this->getMockConnection(['getName'], $pdo); + $connection->method('getName')->willReturn('name'); + $connection->setReconnector(function ($connection) { + $connection->setPdo($this->createMock(DatabaseConnectionTestMockPDO::class)); + }); + $connection->setTransactionManager($manager = new DatabaseTransactionsManager); + + $fired = 0; + $connection->beginTransaction(); + $manager->addCallback(function () use (&$fired) { + $fired++; + }); + + $connection->disconnect(); + + $connection->beginTransaction(); + $connection->commit(); + + $this->assertSame(0, $fired); + } + public function testBeganTransactionFiresEventsIfSet() { $pdo = $this->createMock(DatabaseConnectionTestMockPDO::class);