From 054503aa4f500032f06bf55a52d429df4dd4dd2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jake=C5=A1?= Date: Tue, 26 May 2026 17:09:03 +0100 Subject: [PATCH 1/4] Default SQLite connections to WAL Configure new SQLite connections to use WAL by default and apply synchronous=NORMAL when WAL is the effective journal mode. Keep the explicit SQLITE_JOURNAL_MODE override available for WordPress plugin connections, including initial installation. --- .../src/sqlite/class-wp-sqlite-connection.php | 49 +++++++- .../tests/WP_SQLite_Connection_Tests.php | 115 ++++++++++++++++++ .../wp-includes/sqlite/install-functions.php | 7 +- 3 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php index 1509a1e64..d77027846 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php @@ -19,6 +19,16 @@ class WP_SQLite_Connection { */ const DEFAULT_SQLITE_TIMEOUT = 10; + /** + * The default SQLite journal mode. + */ + const DEFAULT_SQLITE_JOURNAL_MODE = 'WAL'; + + /** + * The default SQLite synchronous setting for WAL mode. + */ + const DEFAULT_SQLITE_WAL_SYNCHRONOUS = 'NORMAL'; + /** * The supported SQLite journal modes. * @@ -33,6 +43,18 @@ class WP_SQLite_Connection { 'OFF', ); + /** + * The supported SQLite synchronous settings. + * + * See: https://www.sqlite.org/pragma.html#pragma_synchronous + */ + const SQLITE_SYNCHRONOUS_SETTINGS = array( + 'OFF', + 'NORMAL', + 'FULL', + 'EXTRA', + ); + /** * The PDO connection for SQLite. * @@ -62,7 +84,9 @@ class WP_SQLite_Connection { * If not provided, a new PDO instance will be created. * @type int|null $timeout Optional. SQLite timeout in seconds. * The time to wait for a writable lock. - * @type string|null $journal_mode Optional. SQLite journal mode. + * @type string|null $journal_mode Optional. SQLite journal mode. Defaults to WAL. + * @type string|null $synchronous Optional. SQLite synchronous setting. Defaults to + * NORMAL when the effective journal mode is WAL. * } * * @throws InvalidArgumentException When some connection options are invalid. @@ -92,9 +116,28 @@ public function __construct( array $options ) { $this->pdo->setAttribute( PDO::ATTR_TIMEOUT, $timeout ); // Configure SQLite journal mode. - $journal_mode = $options['journal_mode'] ?? null; + $effective_journal_mode = null; + $journal_mode = $options['journal_mode'] ?? self::DEFAULT_SQLITE_JOURNAL_MODE; + if ( is_string( $journal_mode ) ) { + $journal_mode = strtoupper( $journal_mode ); + } if ( $journal_mode && in_array( $journal_mode, self::SQLITE_JOURNAL_MODES, true ) ) { - $this->query( 'PRAGMA journal_mode = ' . $journal_mode ); + $effective_journal_mode = strtoupper( + (string) $this->query( 'PRAGMA journal_mode = ' . $journal_mode )->fetchColumn() + ); + } + + // Configure SQLite synchronous setting. In WAL mode, default to NORMAL. + // Otherwise, use SQLite's default value. + $synchronous = $options['synchronous'] ?? null; + if ( null === $synchronous && 'WAL' === $effective_journal_mode ) { + $synchronous = self::DEFAULT_SQLITE_WAL_SYNCHRONOUS; + } + if ( is_string( $synchronous ) ) { + $synchronous = strtoupper( $synchronous ); + } + if ( $synchronous && in_array( $synchronous, self::SQLITE_SYNCHRONOUS_SETTINGS, true ) ) { + $this->query( 'PRAGMA synchronous = ' . $synchronous ); } } diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php b/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php new file mode 100644 index 000000000..6a075d884 --- /dev/null +++ b/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php @@ -0,0 +1,115 @@ +db_path = tempnam( sys_get_temp_dir(), 'wp_sqlite_' ); + unlink( $this->db_path ); + } + + public function tearDown(): void { + foreach ( array( + $this->db_path, + $this->db_path . '-wal', + $this->db_path . '-shm', + $this->db_path . '-journal', + ) as $path ) { + if ( is_string( $path ) && file_exists( $path ) ) { + unlink( $path ); + } + } + $this->db_path = null; + } + + public function testDefaultJournalModeUsesWal(): void { + $connection = new WP_SQLite_Connection( array( 'path' => $this->db_path ) ); + + $this->assertSame( 'wal', $this->get_journal_mode( $connection ) ); + $this->assertSame( '1', $this->get_synchronous( $connection ) ); + } + + public function testJournalModeCanBeOverridden(): void { + $connection = new WP_SQLite_Connection( + array( + 'path' => $this->db_path, + 'journal_mode' => 'DELETE', + ) + ); + + $this->assertSame( 'delete', $this->get_journal_mode( $connection ) ); + } + + public function testSynchronousCanBeOverridden(): void { + $connection = new WP_SQLite_Connection( + array( + 'path' => $this->db_path, + 'synchronous' => 'FULL', + ) + ); + + $this->assertSame( '2', $this->get_synchronous( $connection ) ); + } + + public function testRollbackJournalModeKeepsDefaultSynchronous(): void { + $connection = new WP_SQLite_Connection( + array( + 'path' => $this->db_path, + 'journal_mode' => 'DELETE', + ) + ); + + $this->assertSame( '2', $this->get_synchronous( $connection ) ); + } + + public function testInMemoryDatabaseKeepsDefaultSynchronous(): void { + $connection = new WP_SQLite_Connection( array( 'path' => ':memory:' ) ); + + $this->assertSame( 'memory', $this->get_journal_mode( $connection ) ); + $this->assertSame( '2', $this->get_synchronous( $connection ) ); + } + + public function testJournalModeAndSynchronousAreCaseInsensitive(): void { + $connection = new WP_SQLite_Connection( + array( + 'path' => $this->db_path, + 'journal_mode' => 'delete', + 'synchronous' => 'extra', + ) + ); + + $this->assertSame( 'delete', $this->get_journal_mode( $connection ) ); + $this->assertSame( '3', $this->get_synchronous( $connection ) ); + } + + public function testInvalidJournalModeAndSynchronousAreIgnored(): void { + $connection = new WP_SQLite_Connection( + array( + 'path' => $this->db_path, + 'journal_mode' => 'INVALID', + 'synchronous' => 'INVALID', + ) + ); + + $this->assertSame( 'delete', $this->get_journal_mode( $connection ) ); + $this->assertSame( '2', $this->get_synchronous( $connection ) ); + } + + private function get_journal_mode( WP_SQLite_Connection $connection ): string { + return strtolower( (string) $connection->query( 'PRAGMA journal_mode' )->fetchColumn() ); + } + + private function get_synchronous( WP_SQLite_Connection $connection ): string { + return (string) $connection->query( 'PRAGMA synchronous' )->fetchColumn(); + } +} diff --git a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php index 5d73e39eb..e4788dbe9 100644 --- a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php +++ b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php @@ -35,7 +35,12 @@ function sqlite_make_db_sqlite() { } $translator = new WP_SQLite_Driver( - new WP_SQLite_Connection( array( 'pdo' => $pdo ) ), + new WP_SQLite_Connection( + array( + 'pdo' => $pdo, + 'journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null, + ) + ), $wpdb->dbname ); $query = null; From 5b4c913d6ca5969a67af58db547eeebb09e4acef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jake=C5=A1?= Date: Fri, 12 Jun 2026 13:10:12 +0200 Subject: [PATCH 2/4] Fall back to the current journal mode when WAL is unavailable WAL can fail to engage in some environments, e.g., on network filesystems or when the WAL sidecar files cannot be created. In that case, setting the journal mode throws, which would newly fail connections that worked before WAL became the default. Keep the database's current journal mode when the WAL default fails, but let explicitly configured modes surface the error. Also include the SQLite connection setup in the installation error handling, so a connection failure dies gracefully during WordPress installation instead of causing a fatal error. --- .../src/sqlite/class-wp-sqlite-connection.php | 15 ++++- .../tests/WP_SQLite_Connection_Tests.php | 57 ++++++++++++++++++- .../wp-includes/sqlite/install-functions.php | 26 ++++----- 3 files changed, 80 insertions(+), 18 deletions(-) diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php index d77027846..2908a3ceb 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php @@ -122,9 +122,18 @@ public function __construct( array $options ) { $journal_mode = strtoupper( $journal_mode ); } if ( $journal_mode && in_array( $journal_mode, self::SQLITE_JOURNAL_MODES, true ) ) { - $effective_journal_mode = strtoupper( - (string) $this->query( 'PRAGMA journal_mode = ' . $journal_mode )->fetchColumn() - ); + try { + $effective_journal_mode = strtoupper( + (string) $this->query( 'PRAGMA journal_mode = ' . $journal_mode )->fetchColumn() + ); + } catch ( PDOException $e ) { + // WAL may be unavailable in some environments, such as on network + // filesystems. When it is explicitly configured, surface the error. + // Otherwise, fall back to the default SQLite behavior. + if ( isset( $options['journal_mode'] ) ) { + throw $e; + } + } } // Configure SQLite synchronous setting. In WAL mode, default to NORMAL. diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php b/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php index 6a075d884..b114eaeaa 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php @@ -6,6 +6,13 @@ * Tests for the SQLite connection setup. */ class WP_SQLite_Connection_Tests extends TestCase { + /** + * Path to the temporary directory holding the SQLite database file. + * + * @var string|null + */ + private $db_dir; + /** * Path to the temporary SQLite database file used in file-based tests. * @@ -14,11 +21,14 @@ class WP_SQLite_Connection_Tests extends TestCase { private $db_path; public function setUp(): void { - $this->db_path = tempnam( sys_get_temp_dir(), 'wp_sqlite_' ); - unlink( $this->db_path ); + $this->db_dir = tempnam( sys_get_temp_dir(), 'wp_sqlite_' ); + unlink( $this->db_dir ); + mkdir( $this->db_dir ); + $this->db_path = $this->db_dir . '/database.sqlite'; } public function tearDown(): void { + chmod( $this->db_dir, 0755 ); // Restore permissions changed by read-only tests. foreach ( array( $this->db_path, $this->db_path . '-wal', @@ -29,6 +39,8 @@ public function tearDown(): void { unlink( $path ); } } + rmdir( $this->db_dir ); + $this->db_dir = null; $this->db_path = null; } @@ -105,6 +117,47 @@ public function testInvalidJournalModeAndSynchronousAreIgnored(): void { $this->assertSame( '2', $this->get_synchronous( $connection ) ); } + public function testDefaultJournalModeFallsBackWhenWalIsUnavailable(): void { + $this->make_database_directory_read_only(); + + $connection = new WP_SQLite_Connection( array( 'path' => $this->db_path ) ); + + $this->assertSame( 'delete', $this->get_journal_mode( $connection ) ); + $this->assertSame( '2', $this->get_synchronous( $connection ) ); + } + + public function testExplicitJournalModeSurfacesFailureWhenWalIsUnavailable(): void { + $this->make_database_directory_read_only(); + + $this->expectException( PDOException::class ); + new WP_SQLite_Connection( + array( + 'path' => $this->db_path, + 'journal_mode' => 'WAL', + ) + ); + } + + /** + * Create the database file first, and then make its directory read-only, + * so that the WAL sidecar files ("-wal", "-shm") cannot be created. + */ + private function make_database_directory_read_only(): void { + $connection = new WP_SQLite_Connection( + array( + 'path' => $this->db_path, + 'journal_mode' => 'DELETE', + ) + ); + $connection->query( 'CREATE TABLE t ( id INTEGER )' ); + $connection = null; + + chmod( $this->db_dir, 0555 ); + if ( is_writable( $this->db_dir ) ) { + $this->markTestSkipped( 'The test requires a non-writable database directory.' ); + } + } + private function get_journal_mode( WP_SQLite_Connection $connection ): string { return strtolower( (string) $connection->query( 'PRAGMA journal_mode' )->fetchColumn() ); } diff --git a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php index e4788dbe9..ec73f2f04 100644 --- a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php +++ b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php @@ -25,25 +25,25 @@ function sqlite_make_db_sqlite() { $table_schemas = wp_get_db_schema(); $queries = explode( ';', $table_schemas ); try { - $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO - $pdo = new $pdo_class( 'sqlite:' . FQDB, null, null, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ) ); // phpcs:ignore WordPress.DB.RestrictedClasses + $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO + $pdo = new $pdo_class( 'sqlite:' . FQDB, null, null, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ) ); // phpcs:ignore WordPress.DB.RestrictedClasses + $translator = new WP_SQLite_Driver( + new WP_SQLite_Connection( + array( + 'pdo' => $pdo, + 'journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null, + ) + ), + $wpdb->dbname + ); } catch ( PDOException $err ) { $err_data = $err->errorInfo; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $message = 'Database connection error!
'; - $message .= sprintf( 'Error message is: %s', $err_data[2] ); + $message .= sprintf( 'Error message is: %s', $err_data[2] ?? $err->getMessage() ); wp_die( $message, 'Database Error!' ); } - $translator = new WP_SQLite_Driver( - new WP_SQLite_Connection( - array( - 'pdo' => $pdo, - 'journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null, - ) - ), - $wpdb->dbname - ); - $query = null; + $query = null; try { $translator->begin_transaction(); From 9bfb3ace093321deb26fb98ef97059cd3af0c2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jake=C5=A1?= Date: Fri, 12 Jun 2026 13:11:32 +0200 Subject: [PATCH 3/4] Accept integer synchronous setting values PRAGMA synchronous accepts integers from 0 to 3 as equivalents of the keyword values, and constants like SQLITE_SYNCHRONOUS are likely to be defined as integers. Map integer values to the corresponding keywords instead of silently ignoring them. --- .../src/sqlite/class-wp-sqlite-connection.php | 27 ++++++++++--------- .../tests/WP_SQLite_Connection_Tests.php | 23 ++++++++++++++++ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php index 2908a3ceb..fe7ef881e 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php @@ -46,6 +46,8 @@ class WP_SQLite_Connection { /** * The supported SQLite synchronous settings. * + * The list is indexed by the corresponding numeric setting values (0 to 3). + * * See: https://www.sqlite.org/pragma.html#pragma_synchronous */ const SQLITE_SYNCHRONOUS_SETTINGS = array( @@ -77,16 +79,16 @@ class WP_SQLite_Connection { * @param array $options { * An array of options. * - * @type string|null $path Optional. SQLite database path. - * For in-memory database, use ':memory:'. - * Must be set when PDO instance is not provided. - * @type PDO|null $pdo Optional. PDO instance with SQLite connection. - * If not provided, a new PDO instance will be created. - * @type int|null $timeout Optional. SQLite timeout in seconds. - * The time to wait for a writable lock. - * @type string|null $journal_mode Optional. SQLite journal mode. Defaults to WAL. - * @type string|null $synchronous Optional. SQLite synchronous setting. Defaults to - * NORMAL when the effective journal mode is WAL. + * @type string|null $path Optional. SQLite database path. + * For in-memory database, use ':memory:'. + * Must be set when PDO instance is not provided. + * @type PDO|null $pdo Optional. PDO instance with SQLite connection. + * If not provided, a new PDO instance will be created. + * @type int|null $timeout Optional. SQLite timeout in seconds. + * The time to wait for a writable lock. + * @type string|null $journal_mode Optional. SQLite journal mode. Defaults to WAL. + * @type string|int|null $synchronous Optional. SQLite synchronous setting. Defaults to + * NORMAL when the effective journal mode is WAL. * } * * @throws InvalidArgumentException When some connection options are invalid. @@ -141,8 +143,9 @@ public function __construct( array $options ) { $synchronous = $options['synchronous'] ?? null; if ( null === $synchronous && 'WAL' === $effective_journal_mode ) { $synchronous = self::DEFAULT_SQLITE_WAL_SYNCHRONOUS; - } - if ( is_string( $synchronous ) ) { + } elseif ( is_int( $synchronous ) && isset( self::SQLITE_SYNCHRONOUS_SETTINGS[ $synchronous ] ) ) { + $synchronous = self::SQLITE_SYNCHRONOUS_SETTINGS[ $synchronous ]; + } elseif ( is_string( $synchronous ) ) { $synchronous = strtoupper( $synchronous ); } if ( $synchronous && in_array( $synchronous, self::SQLITE_SYNCHRONOUS_SETTINGS, true ) ) { diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php b/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php index b114eaeaa..c5ef606d1 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php @@ -117,6 +117,29 @@ public function testInvalidJournalModeAndSynchronousAreIgnored(): void { $this->assertSame( '2', $this->get_synchronous( $connection ) ); } + public function testSynchronousAcceptsIntegerValues(): void { + $connection = new WP_SQLite_Connection( + array( + 'path' => $this->db_path, + 'synchronous' => 3, + ) + ); + + $this->assertSame( '3', $this->get_synchronous( $connection ) ); + } + + public function testSynchronousAcceptsIntegerZero(): void { + $connection = new WP_SQLite_Connection( + array( + 'path' => $this->db_path, + 'journal_mode' => 'DELETE', + 'synchronous' => 0, + ) + ); + + $this->assertSame( '0', $this->get_synchronous( $connection ) ); + } + public function testDefaultJournalModeFallsBackWhenWalIsUnavailable(): void { $this->make_database_directory_read_only(); From 1898fe05517286acff682e15665acd0b7d40ad88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jake=C5=A1?= Date: Fri, 12 Jun 2026 13:13:18 +0200 Subject: [PATCH 4/4] Pass journal mode and synchronous options through the PDO API The WAL default applies to all WP_SQLite_Connection consumers, but only the WordPress plugin paths supported overriding it. Accept journal_mode and synchronous in the WP_PDO_MySQL_On_SQLite driver options so the PDO API consumers can configure them as well. --- .../sqlite/class-wp-pdo-mysql-on-sqlite.php | 9 ++- .../WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php | 56 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-mysql-on-sqlite.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-mysql-on-sqlite.php index 7130fb631..4e9726342 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-mysql-on-sqlite.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-mysql-on-sqlite.php @@ -669,11 +669,16 @@ public function __construct( $db_name = $args['dbname'] ?? 'sqlite_database'; // Create a new SQLite connection. + $connection_options = array( + 'journal_mode' => $options['journal_mode'] ?? null, + 'synchronous' => $options['synchronous'] ?? null, + ); if ( isset( $options['pdo'] ) ) { - $this->connection = new WP_SQLite_Connection( array( 'pdo' => $options['pdo'] ) ); + $connection_options['pdo'] = $options['pdo']; } else { - $this->connection = new WP_SQLite_Connection( array( 'path' => $path ) ); + $connection_options['path'] = $path; } + $this->connection = new WP_SQLite_Connection( $connection_options ); $this->mysql_version = $options['mysql_version'] ?? 80038; $this->main_db_name = $db_name; diff --git a/packages/mysql-on-sqlite/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php b/packages/mysql-on-sqlite/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php index 9ac8a3014..404481a34 100644 --- a/packages/mysql-on-sqlite/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php @@ -68,6 +68,54 @@ public function test_dsn_parsing(): void { $this->assertSame( 'w', $driver->query( 'SELECT DATABASE()' )->fetch()[0] ); } + public function test_journal_mode_defaults_to_wal(): void { + $path = tempnam( sys_get_temp_dir(), 'wp_sqlite_' ); + unlink( $path ); + + try { + $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=' . $path . ';dbname=wp' ); + $connection = $driver->get_connection(); + $this->assertSame( + 'wal', + strtolower( (string) $connection->query( 'PRAGMA journal_mode' )->fetchColumn() ) + ); + $this->assertSame( + '1', + (string) $connection->query( 'PRAGMA synchronous' )->fetchColumn() + ); + } finally { + $this->remove_database_files( $path ); + } + } + + public function test_journal_mode_and_synchronous_driver_options(): void { + $path = tempnam( sys_get_temp_dir(), 'wp_sqlite_' ); + unlink( $path ); + + try { + $driver = new WP_PDO_MySQL_On_SQLite( + 'mysql-on-sqlite:path=' . $path . ';dbname=wp', + null, + null, + array( + 'journal_mode' => 'DELETE', + 'synchronous' => 'FULL', + ) + ); + $connection = $driver->get_connection(); + $this->assertSame( + 'delete', + strtolower( (string) $connection->query( 'PRAGMA journal_mode' )->fetchColumn() ) + ); + $this->assertSame( + '2', + (string) $connection->query( 'PRAGMA synchronous' )->fetchColumn() + ); + } finally { + $this->remove_database_files( $path ); + } + } + public function test_query(): void { $result = $this->driver->query( "SELECT 1, 'abc'" ); $this->assertInstanceOf( PDOStatement::class, $result ); @@ -548,4 +596,12 @@ public function data_pdo_fetch_methods(): Generator { ), ); } + + private function remove_database_files( string $path ): void { + foreach ( array( $path, $path . '-wal', $path . '-shm', $path . '-journal' ) as $file ) { + if ( file_exists( $file ) ) { + unlink( $file ); + } + } + } }