Skip to content

Commit 0f7060f

Browse files
committed
Configure the SQLite driver using an $options array
1 parent c27b571 commit 0f7060f

5 files changed

Lines changed: 100 additions & 41 deletions

File tree

tests/WP_SQLite_Driver_Tests.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ public static function setUpBeforeClass(): void {
3535
public function setUp(): void {
3636
$this->sqlite = new PDO( 'sqlite::memory:' );
3737

38-
$this->engine = new WP_SQLite_Driver( 'wp', $this->sqlite );
38+
$this->engine = new WP_SQLite_Driver(
39+
array(
40+
'connection' => $this->sqlite,
41+
'database' => 'wp',
42+
)
43+
);
3944
$this->engine->query(
4045
"CREATE TABLE _options (
4146
ID INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,

tests/WP_SQLite_Driver_Translation_Tests.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ public static function setUpBeforeClass(): void {
2323
}
2424

2525
public function setUp(): void {
26-
$this->driver = new WP_SQLite_Driver( 'wp', new PDO( 'sqlite::memory:' ) );
26+
$this->driver = new WP_SQLite_Driver(
27+
array(
28+
'path' => ':memory:',
29+
'database' => 'wp',
30+
)
31+
);
2732
}
2833

2934
public function testSelect(): void {

tests/tools/dump-sqlite-query.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php';
1212
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver.php';
1313

14-
$driver = new WP_SQLite_Driver( 'wp', new PDO( 'sqlite::memory:' ) );
14+
$driver = new WP_SQLite_Driver(
15+
array(
16+
'path' => ':memory:',
17+
'database' => 'wp',
18+
)
19+
);
1520

1621
$query = "SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.t1_id WHERE t1.name = 'abc'";
1722

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

Lines changed: 74 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -311,68 +311,105 @@ class WP_SQLite_Driver {
311311
/**
312312
* Constructor.
313313
*
314-
* Create PDO object, set user defined functions and initialize other settings.
315-
* Don't use parent::__construct() because this class does not only returns
316-
* PDO instance but many others jobs.
314+
* Set up an SQLite connection and the MySQL-on-SQLite driver.
317315
*
318-
* @param string $db_name The database name. In WordPress, the value of DB_NAME.
319-
* @param PDO|null $pdo The PDO object.
316+
* @param array $options {
317+
* An array of options.
318+
*
319+
* @type string $database Database name.
320+
* The name of the emulated MySQL database.
321+
* @type string|null $path Optional. SQLite database path.
322+
* For in-memory database, use ':memory:'.
323+
* Must be set when PDO instance is not provided.
324+
* @type PDO|null $connection Optional. PDO instance with SQLite connection.
325+
* If not provided, a new PDO instance will be created.
326+
* @type int|null $timeout Optional. SQLite timeout in seconds.
327+
* The time to wait for a writable lock.
328+
* @type string|null $sqlite_journal_mode Optional. SQLite journal mode.
329+
* }
320330
*/
321-
public function __construct( string $db_name, ?PDO $pdo = null ) {
322-
$this->db_name = $db_name;
323-
if ( ! $pdo ) {
324-
if ( ! is_file( FQDB ) ) {
331+
public function __construct( array $options ) {
332+
// Database name.
333+
if ( ! isset( $options['database'] ) || ! is_string( $options['database'] ) ) {
334+
throw new InvalidArgumentException( 'Option "database" is required.' );
335+
}
336+
$this->db_name = $options['database'];
337+
338+
// Database connection.
339+
if ( isset( $options['connection'] ) && $options['connection'] instanceof PDO ) {
340+
$this->pdo = $options['connection'];
341+
}
342+
343+
// Create a PDO connection if it is not provided.
344+
if ( ! $this->pdo ) {
345+
if ( ! isset( $options['path'] ) || ! is_string( $options['path'] ) ) {
346+
throw new InvalidArgumentException( 'Option "path" is required when "connection" is not provided.' );
347+
}
348+
$path = $options['path'];
349+
350+
if ( ':memory:' !== $path && ! is_file( $path ) ) {
325351
$this->prepare_directory();
326352
}
327353

328354
try {
329-
$options = array(
330-
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
331-
PDO::ATTR_STRINGIFY_FETCHES => true,
332-
PDO::ATTR_TIMEOUT => self::DEFAULT_TIMEOUT,
333-
);
334-
335-
$dsn = 'sqlite:' . FQDB;
336-
$pdo = new PDO( $dsn, null, null, $options );
337-
} catch ( PDOException $ex ) {
355+
$this->pdo = new PDO( 'sqlite:' . $path );
356+
} catch ( PDOException $e ) {
338357
$this->error_messages[] = sprintf(
339358
'<p>%s</p><p>%s</p><p>%s</p>',
340359
'Database initialization error!',
341-
'Code: ' . $ex->getCode(),
342-
'Error Message: ' . $ex->getMessage()
360+
'Code: ' . $e->getCode(),
361+
'Error Message: ' . $e->getMessage()
343362
);
344363
return;
345364
}
346365
}
347366

348-
WP_SQLite_PDO_User_Defined_Functions::register_for( $pdo );
367+
// Throw exceptions on error.
368+
$this->pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
349369

350-
// MySQL data comes across stringified by default.
351-
$pdo->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true );
370+
// Configure SQLite timeout.
371+
if ( isset( $options['timeout'] ) && is_int( $options['timeout'] ) ) {
372+
$timeout = $options['timeout'];
373+
} else {
374+
$timeout = self::DEFAULT_TIMEOUT;
375+
}
376+
$this->pdo->setAttribute( PDO::ATTR_TIMEOUT, $timeout );
352377

353-
$this->pdo = $pdo;
378+
// Return all values (except null) as strings.
379+
$this->pdo->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true );
354380

355-
$this->information_schema_builder = new WP_SQLite_Information_Schema_Builder(
356-
$this->db_name,
357-
array( $this, 'execute_sqlite_query' )
358-
);
359-
$this->information_schema_builder->ensure_information_schema_tables();
381+
// Enable foreign keys. By default, they are off.
382+
$this->pdo->query( 'PRAGMA foreign_keys = ON' );
383+
384+
// Configure SQLite journal mode.
385+
if (
386+
isset( $options['sqlite_journal_mode'] )
387+
&& in_array(
388+
$options['sqlite_journal_mode'],
389+
array( 'DELETE', 'TRUNCATE', 'PERSIST', 'MEMORY', 'WAL', 'OFF' ),
390+
true
391+
)
392+
) {
393+
$this->pdo->query( 'PRAGMA journal_mode = ' . $options['sqlite_journal_mode'] );
394+
}
395+
396+
// Register SQLite functions.
397+
WP_SQLite_PDO_User_Defined_Functions::register_for( $this->pdo );
360398

361399
// Load MySQL grammar.
362400
if ( null === self::$grammar ) {
363401
self::$grammar = new WP_Parser_Grammar( require self::GRAMMAR_PATH );
364402
}
365403

404+
// Initialize information schema builder.
405+
$this->information_schema_builder = new WP_SQLite_Information_Schema_Builder(
406+
$this->db_name,
407+
array( $this, 'execute_sqlite_query' )
408+
);
409+
$this->information_schema_builder->ensure_information_schema_tables();
410+
366411
// Load SQLite version to a property used by WordPress health info.
367412
$this->client_info = $this->get_sqlite_version();
368-
369-
$this->pdo->query( 'PRAGMA foreign_keys = ON' );
370-
$this->pdo->query( 'PRAGMA encoding="UTF-8";' );
371-
372-
$valid_journal_modes = array( 'DELETE', 'TRUNCATE', 'PERSIST', 'MEMORY', 'WAL', 'OFF' );
373-
if ( defined( 'SQLITE_JOURNAL_MODE' ) && in_array( SQLITE_JOURNAL_MODE, $valid_journal_modes, true ) ) {
374-
$this->pdo->query( 'PRAGMA journal_mode = ' . SQLITE_JOURNAL_MODE );
375-
}
376413
}
377414

378415
/**

wp-includes/sqlite/class-wp-sqlite-db.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,14 @@ public function db_connect( $allow_bail = true ) {
239239
require_once __DIR__ . '/../../wp-includes/mysql/class-wp-mysql-parser.php';
240240
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver.php';
241241
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php';
242-
$this->dbh = new WP_SQLite_Driver( 'wp', $pdo );
242+
$this->dbh = new WP_SQLite_Driver(
243+
array(
244+
'connection' => $pdo,
245+
'path' => FQDB,
246+
'database' => $this->dbname,
247+
'sqlite_journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null,
248+
)
249+
);
243250
} else {
244251
$this->dbh = new WP_SQLite_Translator( $pdo );
245252
}

0 commit comments

Comments
 (0)