Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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.
*
Expand Down Expand Up @@ -63,6 +85,7 @@ class WP_SQLite_Connection {
* @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 $synchronous Optional. SQLite synchronous setting.
* }
*
* @throws InvalidArgumentException When some connection options are invalid.
Expand Down Expand Up @@ -92,9 +115,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.
$synchronous = $options['synchronous'] ?? null;
if ( null === $synchronous && 'WAL' === $effective_journal_mode ) {
// Keep rollback journal modes on SQLite's default durability unless explicitly configured.
$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 );
}
}

Expand Down
75 changes: 75 additions & 0 deletions packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

use PHPUnit\Framework\TestCase;

/**
* Tests for the SQLite connection setup.
*/
class WP_SQLite_Connection_Tests extends TestCase {
/**
* Path to the temporary SQLite database file used in file-based tests.
*
* @var string|null
*/
private $db_path;

public function setUp(): void {
$this->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',
strtolower( (string) $connection->query( 'PRAGMA journal_mode' )->fetchColumn() )
);
$this->assertSame(
'1',
(string) $connection->query( 'PRAGMA synchronous' )->fetchColumn()
);
}

public function testJournalModeCanBeOverridden(): void {
$connection = new WP_SQLite_Connection(
array(
'path' => $this->db_path,
'journal_mode' => 'DELETE',
)
);

$this->assertSame(
'delete',
strtolower( (string) $connection->query( 'PRAGMA journal_mode' )->fetchColumn() )
);
}

public function testSynchronousCanBeOverridden(): void {
$connection = new WP_SQLite_Connection(
array(
'path' => $this->db_path,
'synchronous' => 'FULL',
)
);

$this->assertSame(
'2',
(string) $connection->query( 'PRAGMA synchronous' )->fetchColumn()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ public function db_connect( $allow_bail = true ) {
'pdo' => $pdo,
'path' => FQDB,
'journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null,
'synchronous' => defined( 'SQLITE_SYNCHRONOUS' ) ? SQLITE_SYNCHRONOUS : null,
)
);
$this->dbh = new WP_SQLite_Driver( $connection, $this->dbname );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ 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,
'synchronous' => defined( 'SQLITE_SYNCHRONOUS' ) ? SQLITE_SYNCHRONOUS : null,
)
),
$wpdb->dbname
);
$query = null;
Expand Down
Loading