From 639051914e931daee3463c66eb9f305032b33d2b Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Wed, 10 Dec 2025 11:30:40 +0100 Subject: [PATCH 1/4] Add a loader file for the MySQL-on-SQLite driver --- .../src/Adapter/class-sqlite-adapter.php | 19 +---------------- tests/bootstrap.php | 16 +------------- tests/tools/dump-sqlite-query.php | 16 +------------- wp-includes/sqlite/class-wp-sqlite-db.php | 15 +------------ wp-pdo-mysql-on-sqlite.php | 21 +++++++++++++++++++ 5 files changed, 25 insertions(+), 62 deletions(-) create mode 100644 wp-pdo-mysql-on-sqlite.php diff --git a/packages/wp-mysql-proxy/src/Adapter/class-sqlite-adapter.php b/packages/wp-mysql-proxy/src/Adapter/class-sqlite-adapter.php index 1df4165c..adcf88ef 100644 --- a/packages/wp-mysql-proxy/src/Adapter/class-sqlite-adapter.php +++ b/packages/wp-mysql-proxy/src/Adapter/class-sqlite-adapter.php @@ -9,24 +9,7 @@ use WP_SQLite_Driver; use WP_MySQL_Proxy\MySQL_Protocol; -define( 'SQLITE_DRIVER_PATH', __DIR__ . '/../../../..' ); - -require_once SQLITE_DRIVER_PATH . '/version.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/parser/class-wp-parser-grammar.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/parser/class-wp-parser.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/parser/class-wp-parser-node.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/parser/class-wp-parser-token.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/mysql/class-wp-mysql-token.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/mysql/class-wp-mysql-lexer.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/mysql/class-wp-mysql-parser.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/sqlite-ast/class-wp-sqlite-connection.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/sqlite-ast/class-wp-sqlite-configurator.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/sqlite-ast/class-wp-sqlite-driver.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-exception.php'; -require_once SQLITE_DRIVER_PATH . '/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php'; +require_once __DIR__ . '/../../../../wp-pdo-mysql-on-sqlite.php'; class SQLite_Adapter implements Adapter { /** @var WP_SQLite_Driver */ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 6acb7baf..10d15e9c 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,26 +1,12 @@ ':memory:' ) ), diff --git a/wp-includes/sqlite/class-wp-sqlite-db.php b/wp-includes/sqlite/class-wp-sqlite-db.php index 1bc00aaa..0af6ac70 100644 --- a/wp-includes/sqlite/class-wp-sqlite-db.php +++ b/wp-includes/sqlite/class-wp-sqlite-db.php @@ -315,20 +315,7 @@ public function db_connect( $allow_bail = true ) { return false; } - require_once __DIR__ . '/../../wp-includes/parser/class-wp-parser-grammar.php'; - require_once __DIR__ . '/../../wp-includes/parser/class-wp-parser.php'; - require_once __DIR__ . '/../../wp-includes/parser/class-wp-parser-node.php'; - require_once __DIR__ . '/../../wp-includes/parser/class-wp-parser-token.php'; - require_once __DIR__ . '/../../wp-includes/mysql/class-wp-mysql-token.php'; - require_once __DIR__ . '/../../wp-includes/mysql/class-wp-mysql-lexer.php'; - require_once __DIR__ . '/../../wp-includes/mysql/class-wp-mysql-parser.php'; - require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-connection.php'; - require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-configurator.php'; - require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver.php'; - require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php'; - require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php'; - require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-exception.php'; - require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php'; + require_once __DIR__ . '/../../wp-pdo-mysql-on-sqlite.php'; $this->ensure_database_directory( FQDB ); try { diff --git a/wp-pdo-mysql-on-sqlite.php b/wp-pdo-mysql-on-sqlite.php new file mode 100644 index 00000000..265d082e --- /dev/null +++ b/wp-pdo-mysql-on-sqlite.php @@ -0,0 +1,21 @@ + Date: Thu, 18 Dec 2025 11:22:02 +0100 Subject: [PATCH 2/4] Rename WP_SQLite_Driver to WP_PDO_MySQL_On_SQLite --- ...I_Tests.php => WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php} | 6 +++--- ...p-sqlite-driver.php => class-wp-pdo-mysql-on-sqlite.php} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename tests/{WP_SQLite_Driver_PDO_API_Tests.php => WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php} (89%) rename wp-includes/sqlite-ast/{class-wp-sqlite-driver.php => class-wp-pdo-mysql-on-sqlite.php} (99%) diff --git a/tests/WP_SQLite_Driver_PDO_API_Tests.php b/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php similarity index 89% rename from tests/WP_SQLite_Driver_PDO_API_Tests.php rename to tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php index 75a55067..c6ac2017 100644 --- a/tests/WP_SQLite_Driver_PDO_API_Tests.php +++ b/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php @@ -2,13 +2,13 @@ use PHPUnit\Framework\TestCase; -class WP_SQLite_Driver_PDO_API_Tests extends TestCase { - /** @var WP_SQLite_Driver */ +class WP_PDO_MySQL_On_SQLite_PDO_API_Tests extends TestCase { + /** @var WP_PDO_MySQL_On_SQLite */ private $driver; public function setUp(): void { $connection = new WP_SQLite_Connection( array( 'path' => ':memory:' ) ); - $this->driver = new WP_SQLite_Driver( $connection, 'wp' ); + $this->driver = new WP_PDO_MySQL_On_SQLite( $connection, 'wp' ); } public function test_begin_transaction(): void { diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-driver.php b/wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php similarity index 99% rename from wp-includes/sqlite-ast/class-wp-sqlite-driver.php rename to wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php index a0b66ce8..a3b327b4 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-driver.php +++ b/wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php @@ -14,7 +14,7 @@ * * The driver requires PDO with the SQLite driver, and the PCRE engine. */ -class WP_SQLite_Driver { +class WP_PDO_MySQL_On_SQLite { /** * The path to the MySQL SQL grammar file. */ From 034c29b9969d422933f0f3c6b61d1a11124b0c46 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Fri, 5 Dec 2025 15:19:44 +0100 Subject: [PATCH 3/4] Reintroduce WP_SQLite_Driver as a temporary proxy exposing legacy API --- ...Information_Schema_Reconstructor_Tests.php | 2 +- .../class-wp-sqlite-configurator.php | 12 +- .../class-wp-sqlite-driver-exception.php | 14 +- .../sqlite-ast/class-wp-sqlite-driver.php | 254 ++++++++++++++++++ ...qlite-information-schema-reconstructor.php | 12 +- wp-pdo-mysql-on-sqlite.php | 1 + 6 files changed, 275 insertions(+), 20 deletions(-) create mode 100644 wp-includes/sqlite-ast/class-wp-sqlite-driver.php diff --git a/tests/WP_SQLite_Information_Schema_Reconstructor_Tests.php b/tests/WP_SQLite_Information_Schema_Reconstructor_Tests.php index 6bf93e85..df88e2e5 100644 --- a/tests/WP_SQLite_Information_Schema_Reconstructor_Tests.php +++ b/tests/WP_SQLite_Information_Schema_Reconstructor_Tests.php @@ -49,7 +49,7 @@ public function setUp(): void { ); $builder = new WP_SQLite_Information_Schema_Builder( - WP_SQLite_Driver::RESERVED_PREFIX, + WP_PDO_MySQL_On_SQLite::RESERVED_PREFIX, $this->engine->get_connection() ); diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-configurator.php b/wp-includes/sqlite-ast/class-wp-sqlite-configurator.php index 62d35d5b..7590c02e 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-configurator.php +++ b/wp-includes/sqlite-ast/class-wp-sqlite-configurator.php @@ -14,7 +14,7 @@ class WP_SQLite_Configurator { /** * The SQLite driver instance. * - * @var WP_SQLite_Driver + * @var WP_PDO_MySQL_On_SQLite */ private $driver; @@ -35,11 +35,11 @@ class WP_SQLite_Configurator { /** * Constructor. * - * @param WP_SQLite_Driver $driver The SQLite driver instance. + * @param WP_PDO_MySQL_On_SQLite $driver The SQLite driver instance. * @param WP_SQLite_Information_Schema_Builder $schema_builder The information schema builder instance. */ public function __construct( - WP_SQLite_Driver $driver, + WP_PDO_MySQL_On_SQLite $driver, WP_SQLite_Information_Schema_Builder $schema_builder ) { $this->driver = $driver; @@ -100,7 +100,7 @@ private function ensure_global_variables_table(): void { sprintf( 'CREATE TABLE IF NOT EXISTS %s (name TEXT PRIMARY KEY, value TEXT)', $this->driver->get_connection()->quote_identifier( - WP_SQLite_Driver::GLOBAL_VARIABLES_TABLE_NAME + WP_PDO_MySQL_On_SQLite::GLOBAL_VARIABLES_TABLE_NAME ) ) ); @@ -260,11 +260,11 @@ private function save_current_driver_version(): void { sprintf( 'INSERT INTO %s (name, value) VALUES (?, ?) ON CONFLICT(name) DO UPDATE SET value = ?', $this->driver->get_connection()->quote_identifier( - WP_SQLite_Driver::GLOBAL_VARIABLES_TABLE_NAME + WP_PDO_MySQL_On_SQLite::GLOBAL_VARIABLES_TABLE_NAME ) ), array( - WP_SQLite_Driver::DRIVER_VERSION_VARIABLE_NAME, + WP_PDO_MySQL_On_SQLite::DRIVER_VERSION_VARIABLE_NAME, SQLITE_DRIVER_VERSION, SQLITE_DRIVER_VERSION, ) diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php b/wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php index 91918bdf..c43aec8a 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php +++ b/wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php @@ -4,20 +4,20 @@ class WP_SQLite_Driver_Exception extends PDOException { /** * The SQLite driver that originated the exception. * - * @var WP_SQLite_Driver + * @var WP_PDO_MySQL_On_SQLite */ private $driver; /** * Constructor. * - * @param WP_SQLite_Driver $driver The SQLite driver that originated the exception. - * @param string $message The exception message. - * @param int|string $code The exception code. In PDO, it can be a string with value of SQLSTATE. - * @param Throwable|null $previous The previous throwable used for the exception chaining. + * @param WP_PDO_MySQL_On_SQLite $driver The SQLite driver that originated the exception. + * @param string $message The exception message. + * @param int|string $code The exception code. In PDO, it can be a string with value of SQLSTATE. + * @param Throwable|null $previous The previous throwable used for the exception chaining. */ public function __construct( - WP_SQLite_Driver $driver, + WP_PDO_MySQL_On_SQLite $driver, string $message, $code = 0, ?Throwable $previous = null @@ -27,7 +27,7 @@ public function __construct( $this->driver = $driver; } - public function getDriver(): WP_SQLite_Driver { + public function getDriver(): WP_PDO_MySQL_On_SQLite { return $this->driver; } } diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-driver.php b/wp-includes/sqlite-ast/class-wp-sqlite-driver.php new file mode 100644 index 00000000..a562ed59 --- /dev/null +++ b/wp-includes/sqlite-ast/class-wp-sqlite-driver.php @@ -0,0 +1,254 @@ +dbh->client_info" - a mysqli-specific abstraction leak. + * + * @TODO: This should be fixed in WordPress core. + * + * See: + * https://github.com/WordPress/wordpress-develop/blob/bcdca3f9925f1d3eca7b78d231837c0caf0c8c24/src/wp-admin/includes/class-wp-debug-data.php#L1579 + * + * @var string + */ + public $client_info; + + /** + * The MySQL-on-SQLite driver instance. + * + * @var WP_PDO_MySQL_On_SQLite + */ + private $mysql_on_sqlite_driver; + + /** + * Constructor. + * + * Set up an SQLite connection and the MySQL-on-SQLite driver. + * + * @param WP_SQLite_Connection $connection A SQLite database connection. + * @param string $database The database name. + * + * @throws WP_SQLite_Driver_Exception When the driver initialization fails. + */ + public function __construct( + WP_SQLite_Connection $connection, + string $database, + int $mysql_version = 80038 + ) { + $this->mysql_on_sqlite_driver = new WP_PDO_MySQL_On_SQLite( $connection, $database, $mysql_version ); + $this->main_db_name = $database; + $this->client_info = $this->mysql_on_sqlite_driver->client_info; + } + + /** + * Get the SQLite connection instance. + * + * @return WP_SQLite_Connection + */ + public function get_connection(): WP_SQLite_Connection { + return $this->mysql_on_sqlite_driver->get_connection(); + } + + /** + * Get the version of the SQLite engine. + * + * @return string SQLite engine version as a string. + */ + public function get_sqlite_version(): string { + return $this->mysql_on_sqlite_driver->get_sqlite_version(); + } + + /** + * Get the SQLite driver version saved in the database. + * + * The saved driver version corresponds to the latest version of the SQLite + * driver that was used to initialize and configure the SQLite database. + * + * @return string SQLite driver version as a string. + * @throws PDOException When the query execution fails. + */ + public function get_saved_driver_version(): string { + return $this->mysql_on_sqlite_driver->get_saved_driver_version(); + } + + /** + * Check if a specific SQL mode is active. + * + * @param string $mode The SQL mode to check. + * @return bool True if the SQL mode is active, false otherwise. + */ + public function is_sql_mode_active( string $mode ): bool { + return $this->mysql_on_sqlite_driver->is_sql_mode_active( $mode ); + } + + /** + * Get the last executed MySQL query. + * + * @return string|null + */ + public function get_last_mysql_query(): ?string { + return $this->mysql_on_sqlite_driver->get_last_mysql_query(); + } + + /** + * Get SQLite queries executed for the last MySQL query. + * + * @return array{ sql: string, params: array }[] + */ + public function get_last_sqlite_queries(): array { + return $this->mysql_on_sqlite_driver->get_last_sqlite_queries(); + } + + /** + * Get the auto-increment value generated for the last query. + * + * @return int|string + */ + public function get_insert_id() { + return $this->mysql_on_sqlite_driver->get_insert_id(); + } + + /** + * @param string $query Full SQL statement string. + * @param int $fetch_mode PDO fetch mode. Default is PDO::FETCH_OBJ. + * @param array ...$fetch_mode_args Additional fetch mode arguments. + * + * @return mixed Return value, depending on the query type. + * + * @throws WP_SQLite_Driver_Exception When the query execution fails. + */ + public function query( string $query, $fetch_mode = PDO::FETCH_OBJ, ...$fetch_mode_args ) { + return $this->mysql_on_sqlite_driver->query( $query, $fetch_mode, ...$fetch_mode_args ); + } + + /** + * Tokenize a MySQL query and initialize a parser. + * + * @param string $query The MySQL query to parse. + * @return WP_MySQL_Parser A parser initialized for the MySQL query. + */ + public function create_parser( string $query ): WP_MySQL_Parser { + return $this->mysql_on_sqlite_driver->create_parser( $query ); + } + + /** + * Get results of the last query. + * + * @return mixed + */ + public function get_query_results() { + return $this->mysql_on_sqlite_driver->get_query_results(); + } + + /** + * Get return value of the last query() function call. + * + * @return mixed + */ + public function get_last_return_value() { + return $this->mysql_on_sqlite_driver->get_last_return_value(); + } + + /** + * Get the number of columns returned by the last emulated query. + * + * @return int + */ + public function get_last_column_count(): int { + return $this->mysql_on_sqlite_driver->get_last_column_count(); + } + + /** + * Get column metadata for results of the last emulated query. + * + * @return array + */ + public function get_last_column_meta(): array { + return $this->mysql_on_sqlite_driver->get_last_column_meta(); + } + + /** + * Execute a query in SQLite. + * + * @param string $sql The query to execute. + * @param array $params The query parameters. + * @throws PDOException When the query execution fails. + * @return PDOStatement The PDO statement object. + */ + public function execute_sqlite_query( string $sql, array $params = array() ): PDOStatement { + return $this->mysql_on_sqlite_driver->execute_sqlite_query( $sql, $params ); + } + + /** + * Begin a new transaction or nested transaction. + */ + public function beginTransaction(): void { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid + $this->mysql_on_sqlite_driver->begin_transaction(); + } + + /** + * A temporary alias for back compatibility. + * + * @see self::beginTransaction() + */ + public function begin_transaction(): void { + $this->beginTransaction(); + } + + /** + * Commit the current transaction or nested transaction. + */ + public function commit(): void { + $this->mysql_on_sqlite_driver->commit(); + } + + /** + * Rollback the current transaction or nested transaction. + */ + public function rollback(): void { + $this->mysql_on_sqlite_driver->rollback(); + } + + /** + * Proxy also the private property "$main_db_name", as it is used in tests. + */ + public function __set( string $name, $value ): void { + if ( 'main_db_name' === $name ) { + $closure = function ( string $value ) { + $this->main_db_name = $value; + }; + $closure->call( $this->mysql_on_sqlite_driver, $value ); + } + } + + /** + * Proxy also this private method, as it is used in tests. + */ + private function quote_mysql_utf8_string_literal( string $utf8_literal ): string { + $closure = function ( string $utf8_literal ) { + return $this->quote_mysql_utf8_string_literal( $utf8_literal ); + }; + return $closure->call( $this->mysql_on_sqlite_driver, $utf8_literal ); + } +} diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php index c739234b..603e5115 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php +++ b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php @@ -19,7 +19,7 @@ class WP_SQLite_Information_Schema_Reconstructor { /** * The SQLite driver instance. * - * @var WP_SQLite_Driver + * @var WP_PDO_MySQL_On_SQLite */ private $driver; @@ -40,11 +40,11 @@ class WP_SQLite_Information_Schema_Reconstructor { /** * Constructor. * - * @param WP_SQLite_Driver $driver The SQLite driver instance. + * @param WP_PDO_MySQL_On_SQLite $driver The SQLite driver instance. * @param WP_SQLite_Information_Schema_Builder $schema_builder The information schema builder instance. */ public function __construct( - WP_SQLite_Driver $driver, + $driver, WP_SQLite_Information_Schema_Builder $schema_builder ) { $this->driver = $driver; @@ -137,7 +137,7 @@ private function get_sqlite_table_names(): array { array( '_mysql_data_types_cache', 'sqlite\_%', - str_replace( '_', '\_', WP_SQLite_Driver::RESERVED_PREFIX ) . '%', + str_replace( '_', '\_', WP_PDO_MySQL_On_SQLite::RESERVED_PREFIX ) . '%', ) )->fetchAll( PDO::FETCH_COLUMN ); } @@ -692,9 +692,9 @@ private function get_mysql_column_type( string $column_type ): string { /** * Format a MySQL UTF-8 string literal for output in a CREATE TABLE statement. * - * See WP_SQLite_Driver::quote_mysql_utf8_string_literal(). + * See WP_PDO_MySQL_On_SQLite::quote_mysql_utf8_string_literal(). * - * TODO: This is a copy of WP_SQLite_Driver::quote_mysql_utf8_string_literal(). + * TODO: This is a copy of WP_PDO_MySQL_On_SQLite::quote_mysql_utf8_string_literal(). * We may consider extracing it to reusable MySQL helpers. * * @param string $utf8_literal The UTF-8 string literal to escape. diff --git a/wp-pdo-mysql-on-sqlite.php b/wp-pdo-mysql-on-sqlite.php index 265d082e..2061de07 100644 --- a/wp-pdo-mysql-on-sqlite.php +++ b/wp-pdo-mysql-on-sqlite.php @@ -19,3 +19,4 @@ require_once __DIR__ . '/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php'; require_once __DIR__ . '/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-exception.php'; require_once __DIR__ . '/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php'; +require_once __DIR__ . '/wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php'; From 6d98b542509ef7c4a3488e7960933e8c33c255d9 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Thu, 18 Dec 2025 16:29:05 +0100 Subject: [PATCH 4/4] Fix comments mentioning nested transactions --- wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php b/wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php index a3b327b4..8220045b 100644 --- a/wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php +++ b/wp-includes/sqlite-ast/class-wp-pdo-mysql-on-sqlite.php @@ -685,7 +685,7 @@ function ( string $sql, array $params ) { } /** - * PDO API: Begin a new transaction or nested transaction. + * PDO API: Begin a transaction. * * @return bool True on success, false on failure. */ @@ -708,7 +708,7 @@ public function begin_transaction(): void { } /** - * PDO API: Commit the current transaction or nested transaction. + * PDO API: Commit a transaction. * * @return bool True on success, false on failure. */ @@ -721,7 +721,7 @@ public function commit(): bool { } /** - * PDO API: Rollback the current transaction or nested transaction. + * PDO API: Rollback a transaction. * * @return bool True on success, false on failure. */