Skip to content

Commit 816e0b5

Browse files
committed
Fix PDO::inTransaction() for SQLite on PHP < 8.4
1 parent 16bf97e commit 816e0b5

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

wp-includes/sqlite-ast/class-wp-sqlite-driver.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,19 @@ class WP_SQLite_Driver {
504504
*/
505505
private $wrapper_transaction_type = null;
506506

507+
/**
508+
* Whether an SQLite transaction is active in the current session.
509+
*
510+
* This is a polyfill of the "PDO::inTransaction()" method for PHP < 8.4,
511+
* where the "PDO::inTransaction()" method is not reliable with SQLite.
512+
*
513+
* @see https://bugs.php.net/bug.php?id=81227
514+
* @see https://github.com/php/php-src/pull/14268
515+
*
516+
* @var bool
517+
*/
518+
private $in_transaction = false;
519+
507520
/**
508521
* Whether a MySQL table lock is active.
509522
*
@@ -728,6 +741,15 @@ public function rollBack(): bool {
728741
*/
729742
// phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
730743
public function inTransaction(): bool {
744+
if ( PHP_VERSION_ID < 80400 ) {
745+
/*
746+
* On PHP < 8.4, the "PDO::inTransaction()" method is not reliable.
747+
*
748+
* @see https://bugs.php.net/bug.php?id=81227
749+
* @see https://github.com/php/php-src/pull/14268
750+
*/
751+
return $this->in_transaction;
752+
}
731753
return $this->connection->get_pdo()->inTransaction();
732754
}
733755

@@ -1335,6 +1357,7 @@ private function begin_wrapper_transaction(): void {
13351357
$wrapper_transaction_type = 'savepoint';
13361358
} else {
13371359
// For write transactions, we must use "BEGIN IMMEDIATE".
1360+
// @see self::begin_user_transaction() method comments.
13381361
$stmt = $this->connection->prepare( $this->is_readonly ? 'BEGIN' : 'BEGIN IMMEDIATE' );
13391362
$wrapper_transaction_type = 'transaction';
13401363
}
@@ -1343,6 +1366,7 @@ private function begin_wrapper_transaction(): void {
13431366
throw $this->new_driver_exception( 'Failed to begin wrapper transaction.' );
13441367
}
13451368
$this->wrapper_transaction_type = $wrapper_transaction_type;
1369+
$this->in_transaction = true;
13461370
}
13471371

13481372
/**
@@ -1353,17 +1377,20 @@ private function commit_wrapper_transaction(): void {
13531377
return;
13541378
}
13551379

1380+
$in_transaction = $this->in_transaction;
13561381
if ( 'savepoint' === $this->wrapper_transaction_type ) {
13571382
$savepoint_name = $this->get_internal_savepoint_name( 'wrapper' );
13581383
$stmt = $this->connection->prepare( sprintf( 'RELEASE SAVEPOINT %s', $savepoint_name ) );
13591384
} else {
1360-
$stmt = $this->connection->prepare( 'COMMIT' );
1385+
$stmt = $this->connection->prepare( 'COMMIT' );
1386+
$in_transaction = false;
13611387
}
13621388

13631389
if ( ! $stmt->execute() ) {
13641390
throw $this->new_driver_exception( 'Failed to commit wrapper transaction.' );
13651391
}
13661392
$this->wrapper_transaction_type = null;
1393+
$this->in_transaction = $in_transaction;
13671394
}
13681395

13691396
/**
@@ -1386,6 +1413,7 @@ private function begin_user_transaction(): void {
13861413
* @see self::begin_wrapper_transaction()
13871414
*/
13881415
$this->connection->query( 'BEGIN IMMEDIATE' );
1416+
$this->in_transaction = true;
13891417
}
13901418

13911419
/**
@@ -1397,6 +1425,7 @@ private function commit_user_transaction(): void {
13971425
return;
13981426
}
13991427
$this->connection->query( 'COMMIT' );
1428+
$this->in_transaction = false;
14001429
}
14011430

14021431
/**
@@ -1408,6 +1437,7 @@ private function rollback_user_transaction(): void {
14081437
return;
14091438
}
14101439
$this->connection->query( 'ROLLBACK' );
1440+
$this->in_transaction = false;
14111441
}
14121442

14131443
/**

0 commit comments

Comments
 (0)