Skip to content

Commit 5bb9d26

Browse files
committed
transaction via savepoints WIP
1 parent cf6a39e commit 5bb9d26

1 file changed

Lines changed: 35 additions & 26 deletions

File tree

src/Database/Explorer.php

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -238,11 +238,13 @@ public function quote(string $string): string
238238
*/
239239
public function beginTransaction(): void
240240
{
241-
if ($this->transactionDepth !== 0) {
242-
throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
241+
if ($this->transactionDepth === 0) {
242+
$this->logOperation($this->getConnection()->beginTransaction(...), new SqlLiteral('BEGIN TRANSACTION'));
243+
} else {
244+
$this->createSavepoint($this->transactionDepth - 1);
243245
}
244246

245-
$this->logOperation($this->getConnection()->beginTransaction(...), new SqlLiteral('BEGIN TRANSACTION'));
247+
$this->transactionDepth++;
246248
}
247249

248250

@@ -252,11 +254,15 @@ public function beginTransaction(): void
252254
*/
253255
public function commit(): void
254256
{
255-
if ($this->transactionDepth !== 0) {
256-
throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
257-
}
257+
if ($this->transactionDepth === 0) {
258+
throw new \LogicException('No active transaction to commit.');
259+
260+
} elseif (--$this->transactionDepth === 0) {
261+
$this->logOperation($this->getConnection()->commit(...), new SqlLiteral('COMMIT'));
258262

259-
$this->logOperation($this->getConnection()->commit(...), new SqlLiteral('COMMIT'));
263+
} else {
264+
$this->releaseSavepoint($this->transactionDepth);
265+
}
260266
}
261267

262268

@@ -266,11 +272,15 @@ public function commit(): void
266272
*/
267273
public function rollBack(): void
268274
{
269-
if ($this->transactionDepth !== 0) {
270-
throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
271-
}
275+
if ($this->transactionDepth === 0) {
276+
throw new \LogicException('No active transaction to roll back.');
272277

273-
$this->logOperation($this->getConnection()->rollBack(...), new SqlLiteral('ROLLBACK'));
278+
} elseif (--$this->transactionDepth === 0) {
279+
$this->logOperation($this->getConnection()->rollBack(...), new SqlLiteral('ROLLBACK'));
280+
281+
} else {
282+
$this->rollbackToSavepoint($this->transactionDepth);
283+
}
274284
}
275285

276286

@@ -279,28 +289,27 @@ public function rollBack(): void
279289
*/
280290
public function transaction(callable $callback): mixed
281291
{
282-
if ($this->transactionDepth === 0) {
283-
$this->beginTransaction();
284-
}
285-
286-
$this->transactionDepth++;
292+
$this->beginTransaction();
287293
try {
288294
$res = $callback($this);
295+
$this->commit();
296+
return $res;
289297
} catch (\Throwable $e) {
290-
$this->transactionDepth--;
291-
if ($this->transactionDepth === 0) {
292-
$this->rollback();
293-
}
294-
298+
$this->rollBack();
295299
throw $e;
296300
}
301+
}
297302

298-
$this->transactionDepth--;
299-
if ($this->transactionDepth === 0) {
300-
$this->commit();
301-
}
302303

303-
return $res;
304+
public function createSavepoint(int $level): void
305+
{
306+
$this->query('SAVEPOINT LEVEL' . $level); // TODO: to driver, logOperation
307+
}
308+
309+
310+
public function releaseSavepoint(int $level): void
311+
{
312+
$this->query('RELEASE SAVEPOINT LEVEL' . $level);
304313
}
305314

306315

0 commit comments

Comments
 (0)