Skip to content

Commit

Permalink
Add support for nested transactions at the DB adapter level
Browse files Browse the repository at this point in the history
  • Loading branch information
nicksagona committed Dec 7, 2023
1 parent d406540 commit e0dbc0f
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 74 deletions.
43 changes: 43 additions & 0 deletions src/Adapter/AbstractAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ abstract class AbstractAdapter implements AdapterInterface
*/
protected bool $isTransaction = false;

/**
* Transaction depth
* @var int
*/
protected int $transactionDepth = 0;

/**
* Constructor
*
Expand Down Expand Up @@ -150,6 +156,43 @@ public function isTransaction(): bool
return $this->isTransaction;
}

/**
* Get transaction depth
*
* @return int
*/
public function getTransactionDepth(): int
{
return $this->transactionDepth;
}

/**
* Execute complete transaction with the DB adapter
*
* @param mixed $callable
* @param mixed $params
* @throws \Exception
* @return void
*/
public function transaction(mixed $callable, mixed $params = null): void
{
if (!($callable instanceof CallableObject)) {
$callable = new CallableObject($callable, $params);
}

try {
$this->beginTransaction();
$callable->call();
$this->commit();
} catch (\Exception $e) {
if ($this->transactionDepth == 0) {
$this->rollback();
} else {
throw $e;
}
}
}

/**
* Check is transaction is success
*
Expand Down
17 changes: 17 additions & 0 deletions src/Adapter/AdapterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,23 @@ public function rollback(): AdapterInterface;
*/
public function isTransaction(): bool;

/**
* Get transaction depth
*
* @return int
*/
public function getTransactionDepth(): int;

/**
* Execute complete transaction with the DB adapter
*
* @param mixed $callable
* @param mixed $params
* @throws \Exception
* @return void
*/
public function transaction(mixed $callable, mixed $params = null): void;

/**
* Check is transaction is success
*
Expand Down
59 changes: 35 additions & 24 deletions src/Adapter/Mysql.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,18 @@ public function hasOptions(): bool
*/
public function beginTransaction(?int $flags = null, ?string $name = null): Mysql
{
if (($flags !== null) && ($name !== null)) {
$this->connection->begin_transaction($flags, $name);
} else if ($flags !== null) {
$this->connection->begin_transaction($flags);
} else {
$this->connection->begin_transaction();
}
if ($this->transactionDepth == 0) {
if (($flags !== null) && ($name !== null)) {
$this->connection->begin_transaction($flags, $name);
} else if ($flags !== null) {
$this->connection->begin_transaction($flags);
} else {
$this->connection->begin_transaction();
}

$this->isTransaction = true;
$this->isTransaction = true;
$this->transactionDepth++;
}

return $this;
}
Expand All @@ -143,15 +146,19 @@ public function beginTransaction(?int $flags = null, ?string $name = null): Mysq
*/
public function commit(?int $flags = null, ?string $name = null): Mysql
{
if (($flags !== null) && ($name !== null)) {
$this->connection->commit($flags, $name);
} else if ($flags !== null) {
$this->connection->commit($flags);
} else {
$this->connection->commit();
}
$this->transactionDepth--;

$this->isTransaction = false;
if ($this->transactionDepth == 0) {
if (($flags !== null) && ($name !== null)) {
$this->connection->commit($flags, $name);
} else if ($flags !== null) {
$this->connection->commit($flags);
} else {
$this->connection->commit();
}

$this->isTransaction = false;
}

return $this;
}
Expand All @@ -165,15 +172,19 @@ public function commit(?int $flags = null, ?string $name = null): Mysql
*/
public function rollback(?int $flags = null, ?string $name = null): Mysql
{
if (($flags !== null) && ($name !== null)) {
$this->connection->rollback($flags, $name);
} else if ($flags !== null) {
$this->connection->rollback($flags);
} else {
$this->connection->rollback();
}
$this->transactionDepth--;

$this->isTransaction = false;
if ($this->transactionDepth == 0) {
if (($flags !== null) && ($name !== null)) {
$this->connection->rollback($flags, $name);
} else if ($flags !== null) {
$this->connection->rollback($flags);
} else {
$this->connection->rollback();
}

$this->isTransaction = false;
}

return $this;
}
Expand Down
41 changes: 27 additions & 14 deletions src/Adapter/Pdo.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,11 @@ public function getType(): ?string
*/
public function beginTransaction(): Pdo
{
$this->connection->beginTransaction();
$this->isTransaction = true;
if ($this->transactionDepth == 0) {
$this->connection->beginTransaction();
$this->isTransaction = true;
$this->transactionDepth++;
}
return $this;
}

Expand All @@ -194,31 +197,41 @@ public function beginTransaction(): Pdo
*/
public function commit(): Pdo
{
$this->connection->commit();
$this->isTransaction = false;
$this->transactionDepth--;

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

return $this;
}

/**
* Method checks, whether the transaction is initiated.
* Rollback a transaction
*
* @return bool
* @return Pdo
*/
public function inTransaction(): bool
public function rollback(): Pdo
{
return $this->connection->inTransaction();
$this->transactionDepth--;

if ($this->transactionDepth == 0) {
$this->connection->rollBack();
$this->isTransaction = false;
}

return $this;
}

/**
* Rollback a transaction
* Method checks, whether the transaction is initiated.
*
* @return Pdo
* @return bool
*/
public function rollback(): Pdo
public function inTransaction(): bool
{
$this->connection->rollBack();
$this->isTransaction = false;
return $this;
return $this->connection->inTransaction();
}

/**
Expand Down
26 changes: 20 additions & 6 deletions src/Adapter/Pgsql.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,12 @@ public function hasOptions(): bool
*/
public function beginTransaction(): Pgsql
{
$this->query('BEGIN TRANSACTION');
$this->isTransaction = true;
if ($this->transactionDepth == 0) {
$this->query('BEGIN TRANSACTION');
$this->isTransaction = true;
$this->transactionDepth++;
}

return $this;
}

Expand All @@ -165,8 +169,13 @@ public function beginTransaction(): Pgsql
*/
public function commit(): Pgsql
{
$this->query('COMMIT');
$this->isTransaction = false;
$this->transactionDepth--;

if ($this->transactionDepth == 0) {
$this->query('COMMIT');
$this->isTransaction = false;
}

return $this;
}

Expand All @@ -177,8 +186,13 @@ public function commit(): Pgsql
*/
public function rollback(): Pgsql
{
$this->query('ROLLBACK');
$this->isTransaction = false;
$this->transactionDepth--;

if ($this->transactionDepth == 0) {
$this->query('ROLLBACK');
$this->isTransaction = false;
}

return $this;
}

Expand Down
26 changes: 20 additions & 6 deletions src/Adapter/Sqlite.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,12 @@ public function dbFileExists(): bool
*/
public function beginTransaction(): Sqlite
{
$this->query('BEGIN TRANSACTION');
$this->isTransaction = true;
if ($this->transactionDepth == 0) {
$this->query('BEGIN TRANSACTION');
$this->isTransaction = true;
$this->transactionDepth++;
}

return $this;
}

Expand All @@ -146,8 +150,13 @@ public function beginTransaction(): Sqlite
*/
public function commit(): Sqlite
{
$this->query('COMMIT');
$this->isTransaction = false;
$this->transactionDepth--;

if ($this->transactionDepth == 0) {
$this->query('COMMIT');
$this->isTransaction = false;
}

return $this;
}

Expand All @@ -158,8 +167,13 @@ public function commit(): Sqlite
*/
public function rollback(): Sqlite
{
$this->query('ROLLBACK');
$this->isTransaction = false;
$this->transactionDepth--;

if ($this->transactionDepth == 0) {
$this->query('ROLLBACK');
$this->isTransaction = false;
}

return $this;
}

Expand Down
26 changes: 20 additions & 6 deletions src/Adapter/Sqlsrv.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,12 @@ public function hasOptions(): bool
*/
public function beginTransaction(): Sqlsrv
{
sqlsrv_begin_transaction($this->connection);
$this->isTransaction = true;
if ($this->transactionDepth == 0) {
sqlsrv_begin_transaction($this->connection);
$this->isTransaction = true;
$this->transactionDepth++;
}

return $this;
}

Expand All @@ -149,8 +153,13 @@ public function beginTransaction(): Sqlsrv
*/
public function commit(): Sqlsrv
{
sqlsrv_commit($this->connection);
$this->isTransaction = false;
$this->transactionDepth--;

if ($this->transactionDepth == 0) {
sqlsrv_commit($this->connection);
$this->isTransaction = false;
}

return $this;
}

Expand All @@ -161,8 +170,13 @@ public function commit(): Sqlsrv
*/
public function rollback(): Sqlsrv
{
sqlsrv_rollback($this->connection);
$this->isTransaction = false;
$this->transactionDepth--;

if ($this->transactionDepth == 0) {
sqlsrv_rollback($this->connection);
$this->isTransaction = false;
}

return $this;
}

Expand Down
Loading

0 comments on commit e0dbc0f

Please sign in to comment.