Skip to content

Commit

Permalink
Rollback if and only if inside a transaction
Browse files Browse the repository at this point in the history
Similarly to what happens when attempting to commit an already closed
connection when combining PHP 8 and pdo_mysql, an error is thrown when
attempting to rollback. We use the same solution as for commit(), that
is we check that we actually are inside a transaction when possible to do so.

Fixes #1139
  • Loading branch information
greg0ire committed Apr 3, 2021
1 parent 292f7fc commit 6d17f69
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 8 deletions.
2 changes: 1 addition & 1 deletion lib/Doctrine/Migrations/Migrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ private function executeMigration(
$this->configuration->dispatchMigrationEvent(Events::onMigrationsMigrated, $direction, $dryRun);
} catch (Throwable $e) {
if ($allOrNothing) {
$connection->rollBack();
TransactionHelper::rollbackIfInTransaction($connection);
}

throw $e;
Expand Down
23 changes: 19 additions & 4 deletions lib/Doctrine/Migrations/Tools/TransactionHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,28 @@ final class TransactionHelper
{
public static function commitIfInTransaction(Connection $connection): void
{
$wrappedConnection = $connection->getWrappedConnection();

// Attempt to commit while no transaction is running results in exception since PHP 8 + pdo_mysql combination
if ($wrappedConnection instanceof PDO && ! $wrappedConnection->inTransaction()) {
if (! self::inTransaction($connection)) {
return;
}

$connection->commit();
}

public static function rollbackIfInTransaction(Connection $connection): void
{
if (! self::inTransaction($connection)) {
return;
}

$connection->rollBack();
}

private static function inTransaction(Connection $connection): bool
{
$wrappedConnection = $connection->getWrappedConnection();

/* Attempt to commit or rollback while no transaction is running
results in an exception since PHP 8 + pdo_mysql combination */
return ! $wrappedConnection instanceof PDO || $wrappedConnection->inTransaction();
}
}
2 changes: 1 addition & 1 deletion lib/Doctrine/Migrations/Tracking/TableUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function updateMigrationTable(): void
$this->connection->executeQuery($query);
}
} catch (Throwable $e) {
$this->connection->rollBack();
TransactionHelper::rollbackIfInTransaction($this->connection);

throw $e;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Doctrine/Migrations/Version/Executor.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ private function skipMigration(
): void {
if ($migration->isTransactional()) {
//only rollback transaction if in transactional mode
$this->connection->rollBack();
TransactionHelper::rollbackIfInTransaction($this->connection);
}

if (! $migratorConfiguration->isDryRun()) {
Expand Down Expand Up @@ -331,7 +331,7 @@ private function migrationError(Throwable $e, Version $version, AbstractMigratio

if ($migration->isTransactional()) {
//only rollback transaction if in transactional mode
$this->connection->rollBack();
TransactionHelper::rollbackIfInTransaction($this->connection);
}

$version->setState(State::NONE);
Expand Down

0 comments on commit 6d17f69

Please sign in to comment.