Skip to content

Commit dd87630

Browse files
committed
Fix PDO::inTransaction() for SQLite on PHP < 8.4
1 parent aed66fe commit dd87630

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
*
@@ -719,6 +732,15 @@ public function rollBack(): bool {
719732
*/
720733
// phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
721734
public function inTransaction(): bool {
735+
if ( PHP_VERSION_ID < 80400 ) {
736+
/*
737+
* On PHP < 8.4, the "PDO::inTransaction()" method is not reliable.
738+
*
739+
* @see https://bugs.php.net/bug.php?id=81227
740+
* @see https://github.com/php/php-src/pull/14268
741+
*/
742+
return $this->in_transaction;
743+
}
722744
return $this->connection->get_pdo()->inTransaction();
723745
}
724746

@@ -1326,6 +1348,7 @@ private function begin_wrapper_transaction(): void {
13261348
$wrapper_transaction_type = 'savepoint';
13271349
} else {
13281350
// For write transactions, we must use "BEGIN IMMEDIATE".
1351+
// @see self::begin_user_transaction() method comments.
13291352
$stmt = $this->connection->prepare( $this->is_readonly ? 'BEGIN' : 'BEGIN IMMEDIATE' );
13301353
$wrapper_transaction_type = 'transaction';
13311354
}
@@ -1334,6 +1357,7 @@ private function begin_wrapper_transaction(): void {
13341357
throw $this->new_driver_exception( 'Failed to begin wrapper transaction.' );
13351358
}
13361359
$this->wrapper_transaction_type = $wrapper_transaction_type;
1360+
$this->in_transaction = true;
13371361
}
13381362

13391363
/**
@@ -1344,17 +1368,20 @@ private function commit_wrapper_transaction(): void {
13441368
return;
13451369
}
13461370

1371+
$in_transaction = $this->in_transaction;
13471372
if ( 'savepoint' === $this->wrapper_transaction_type ) {
13481373
$savepoint_name = $this->get_internal_savepoint_name( 'wrapper' );
13491374
$stmt = $this->connection->prepare( sprintf( 'RELEASE SAVEPOINT %s', $savepoint_name ) );
13501375
} else {
1351-
$stmt = $this->connection->prepare( 'COMMIT' );
1376+
$stmt = $this->connection->prepare( 'COMMIT' );
1377+
$in_transaction = false;
13521378
}
13531379

13541380
if ( ! $stmt->execute() ) {
13551381
throw $this->new_driver_exception( 'Failed to commit wrapper transaction.' );
13561382
}
13571383
$this->wrapper_transaction_type = null;
1384+
$this->in_transaction = $in_transaction;
13581385
}
13591386

13601387
/**
@@ -1377,6 +1404,7 @@ private function begin_user_transaction(): void {
13771404
* @see self::begin_wrapper_transaction()
13781405
*/
13791406
$this->connection->query( 'BEGIN IMMEDIATE' );
1407+
$this->in_transaction = true;
13801408
}
13811409

13821410
/**
@@ -1388,6 +1416,7 @@ private function commit_user_transaction(): void {
13881416
return;
13891417
}
13901418
$this->connection->query( 'COMMIT' );
1419+
$this->in_transaction = false;
13911420
}
13921421

13931422
/**
@@ -1399,6 +1428,7 @@ private function rollback_user_transaction(): void {
13991428
return;
14001429
}
14011430
$this->connection->query( 'ROLLBACK' );
1431+
$this->in_transaction = false;
14021432
}
14031433

14041434
/**

0 commit comments

Comments
 (0)