Skip to content

Commit

Permalink
Connection::transtaction() call can be nested
Browse files Browse the repository at this point in the history
  • Loading branch information
milo authored and dg committed Apr 5, 2021
1 parent 877dffd commit b00e556
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
20 changes: 17 additions & 3 deletions src/Dibi/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class Connection implements IConnection
/** @var HashMap Substitutes for identifiers */
private $substitutes;

private $transactionDepth = 0;


/**
* Connection options: (see driver-specific options too)
Expand Down Expand Up @@ -407,14 +409,26 @@ public function rollback(string $savepoint = null): void
*/
public function transaction(callable $callback)
{
$this->begin();
if ($this->transactionDepth === 0) {
$this->begin();
}

$this->transactionDepth++;
try {
$res = $callback($this);
} catch (\Throwable $e) {
$this->rollback();
$this->transactionDepth--;
if ($this->transactionDepth === 0) {
$this->rollback();
}
throw $e;
}
$this->commit();

$this->transactionDepth--;
if ($this->transactionDepth === 0) {
$this->commit();
}

return $res;
}

Expand Down
35 changes: 35 additions & 0 deletions tests/dibi/Connection.transactions.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,38 @@ test('transaction() success', function () use ($conn) {
});
Assert::same(5, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
});


test('nested transaction() call fail', function () use ($conn) {
Assert::exception(function () use ($conn) {
$conn->transaction(function (Dibi\Connection $connection) {
$connection->query('INSERT INTO [products]', [
'title' => 'Test product',
]);

$connection->transaction(function (Dibi\Connection $connection2) {
$connection2->query('INSERT INTO [products]', [
'title' => 'Test product',
]);
throw new Exception('my exception');
});
});
}, \Throwable::class, 'my exception');
Assert::same(5, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
});


test('nested transaction() call success', function () use ($conn) {
$conn->transaction(function (Dibi\Connection $connection) {
$connection->query('INSERT INTO [products]', [
'title' => 'Test product',
]);

$connection->transaction(function (Dibi\Connection $connection2) {
$connection2->query('INSERT INTO [products]', [
'title' => 'Test product',
]);
});
});
Assert::same(7, (int) $conn->query('SELECT COUNT(*) FROM [products]')->fetchSingle());
});

0 comments on commit b00e556

Please sign in to comment.