From b55087988d6818b739136c7c80f15c2e2ed131ce Mon Sep 17 00:00:00 2001 From: Konstantin Kalinin Date: Fri, 20 Sep 2019 12:59:32 +0300 Subject: [PATCH] Reset transaction nesting level on connection loss. When the connection is lost or is closed, subsequent transaction will no longer be nested because they started in a brand new session. Our internal representation of the nesting shold take this into account --- lib/Doctrine/DBAL/Connection.php | 2 ++ .../Tests/DBAL/Functional/ConnectionTest.php | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/lib/Doctrine/DBAL/Connection.php b/lib/Doctrine/DBAL/Connection.php index 7fef4e8628a..d5e6b7a048b 100644 --- a/lib/Doctrine/DBAL/Connection.php +++ b/lib/Doctrine/DBAL/Connection.php @@ -354,6 +354,8 @@ public function connect() $this->_conn = $this->_driver->connect($this->params, $user, $password, $driverOptions); $this->isConnected = true; + $this->transactionNestingLevel = 0; + if ($this->autoCommit === false) { $this->beginTransaction(); } diff --git a/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php b/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php index 9218d35e0ab..f9b067ad4a4 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php @@ -70,6 +70,40 @@ public function testTransactionNestingBehavior() : void $this->connection->rollBack(); self::assertEquals(0, $this->connection->getTransactionNestingLevel()); } + + $this->connection->beginTransaction(); + $this->connection->close(); + $this->connection->beginTransaction(); + self::assertEquals(1, $this->connection->getTransactionNestingLevel()); + } + + public function testTransactionNestingLevelIsResetOnReconnect() : void + { + if ($this->connection->getDatabasePlatform()->getName() === 'sqlite') { + $params = $this->connection->getParams(); + $params['memory'] = false; + $params['path'] = '/tmp/test_nesting.sqlite'; + + $connection = DriverManager::getConnection( + $params, + $this->connection->getConfiguration(), + $this->connection->getEventManager() + ); + } else { + $connection = $this->connection; + } + + $connection->executeQuery('CREATE TABLE test_nesting(test int not null)'); + + $this->connection->beginTransaction(); + $this->connection->beginTransaction(); + $connection->close(); // connection closed in runtime (for example if lost or another application logic) + + $connection->beginTransaction(); + $connection->executeQuery('insert into test_nesting values (33)'); + $connection->rollback(); + + self::assertEquals(0, $connection->fetchColumn('select count(*) from test_nesting')); } public function testTransactionNestingBehaviorWithSavepoints() : void