Skip to content
Advertisement

Exception ‘no active transaction’ when using ORMExecutor::execute

I upgraded a legacy project from:

PHP 5.6 -> 8.0

doctrine/orm 2.5.14 -> 2.13.4

doctrine/data-fixtures 1.2.2 -> 1.5.3

Now the following code throws the exception:

PDOException : There is no active transaction /var/www/html/src/vendor/doctrine/dbal/src/Driver/PDO/Connection.php:120 /var/www/html/src/vendor/doctrine/dbal/src/Connection.php:1481 /var/www/html/src/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:280

use DoctrineCommonDataFixturesLoader;
use DoctrineCommonDataFixturesPurgerORMPurger;
use DoctrineCommonDataFixturesExecutorORMExecutor;

$ormPurger = new ORMPurger($entityManager, $exclude);
$ormPurger->setPurgeMode(ORMPurger::PURGE_MODE_TRUNCATE);
$executor = new ORMExecutor($entityManager, $ormPurger);
$executor->execute($loader->getFixtures());

The exception is thrown when DoctrineORMEntityManager::transactional calls:

$this->conn->commit()

In the documentation I read:

Not all RDBMS have the capability to allow TRUNCATE statements inside transactions though. Notably, MySQL will produce the infamous There is no active transaction message when we attempt to close a transaction that was already implicitly closed.

doctrine-data-fixtures/en/latest/explanation/transactions-and-purging.html

— UPDATE

I was able to fix the error by using the default purge mode PURGE_MODE_DELETE instead of PURGE_MODE_TRUNCATE. So does that mean I can’t use TRUNCATE operations when using ORMExecutor::execute?

Advertisement

Answer

RDBMS such as MySQL does not allow TRUNCATE statements inside transactions.

ORMExecutor::execute(array $fixtures, $append = false) perform SQL operations in a transaction. So we have to perform any TRUNCATE operations outside this transaction.

$purger = new ORMPurger($em, $exclude);
$purger->setPurgeMode(ORMPurger::PURGE_MODE_TRUNCATE);
$purger->purge();

$executor = new ORMExecutor($em);
$executor->execute($loader->getFixtures(), append: true);

To use executor without purging we can pass true to the 2nd argument of execute.

// Don't do this unless you want to purge all the tables 
// in the database prior to appending fixtures

$executor->execute($loader->getFixtures(), new ORMPurger());

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement