Skip to content

Commit

Permalink
introduce TransactionRolledBack exception
Browse files Browse the repository at this point in the history
  • Loading branch information
simPod committed Oct 19, 2024
1 parent bebee42 commit 86298fc
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 15 deletions.
4 changes: 3 additions & 1 deletion src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\DBAL\Exception\TransactionRolledBack;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Query\Expression\ExpressionBuilder;
Expand Down Expand Up @@ -1303,7 +1304,8 @@ public function transactional(Closure $func)
} catch (TheDriverException $t) {
$convertedException = $this->handleDriverException($t, null);
$shouldRollback = ! (
$convertedException instanceof UniqueConstraintViolationException
$convertedException instanceof TransactionRolledBack
|| $convertedException instanceof UniqueConstraintViolationException
|| $convertedException instanceof ForeignKeyConstraintViolationException
|| $convertedException instanceof DeadlockException
);
Expand Down
17 changes: 17 additions & 0 deletions src/Driver/API/OCI/ExceptionConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Driver\OCI8\Exception\Error;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\DatabaseDoesNotExist;
use Doctrine\DBAL\Exception\DatabaseObjectNotFoundException;
Expand All @@ -17,9 +18,13 @@
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\TransactionRolledBack;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\DBAL\Query;

use function explode;
use function str_replace;

/** @internal */
final class ExceptionConverter implements ExceptionConverterInterface
{
Expand Down Expand Up @@ -58,6 +63,18 @@ public function convert(Exception $exception, ?Query $query): DriverException
case 1918:
return new DatabaseDoesNotExist($exception, $query);

case 2091:
//ORA-02091: transaction rolled back
//ORA-00001: unique constraint (DOCTRINE.GH3423_UNIQUE) violated
[, $causeError] = explode("\n", $exception->getMessage(), 2);

[$causeCode] = explode(': ', $causeError, 2);
$code = (int) str_replace('ORA-', '', $causeCode);

$why = $this->convert(new Error($causeError, null, $code), $query);

return new TransactionRolledBack($why, $exception, $query);

case 2289:
case 2443:
case 4080:
Expand Down
15 changes: 1 addition & 14 deletions src/Driver/OCI8/Exception/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
use Doctrine\DBAL\Driver\AbstractException;

use function assert;
use function explode;
use function oci_error;
use function str_replace;

/**
* @internal
Expand All @@ -26,17 +24,6 @@ public static function new($resource): self
$error = oci_error($resource);
assert($error !== false);

$code = $error['code'];
$message = $error['message'];
if ($code === self::CODE_TRANSACTION_ROLLED_BACK) {
//ORA-02091: transaction rolled back
//ORA-00001: unique constraint (DOCTRINE.GH3423_UNIQUE) violated
[, $causeError] = explode("\n", $message, 2);

[$causeCode, $message] = explode(': ', $causeError, 2);
$code = (int) str_replace('ORA-', '', $causeCode);
}

return new self($message, null, $code);
return new self($error['message'], null, $error['code']);
}
}
24 changes: 24 additions & 0 deletions src/Exception/TransactionRolledBack.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Doctrine\DBAL\Exception;

use Doctrine\DBAL\Driver\Exception as TheDriverException;
use Doctrine\DBAL\Query;

/** @psalm-immutable */
class TransactionRolledBack extends DriverException
{
private DriverException $why;

public function __construct(DriverException $why, TheDriverException $driverException, ?Query $query)
{
parent::__construct($driverException, $query);

$this->why = $why;
}

public function why(): DriverException
{
return $this->why;
}
}

0 comments on commit 86298fc

Please sign in to comment.