Skip to content
This repository was archived by the owner on Jun 2, 2025. It is now read-only.

Commit 6a641f9

Browse files
committed
Implement a database configurator service for DB initialization and migration
1 parent 767d246 commit 6a641f9

10 files changed

+161
-1
lines changed

load.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* @package wp-sqlite-integration
1313
*/
1414

15+
define( 'SQLITE_DRIVER_VERSION', '2.1.17-alpha' );
1516
define( 'SQLITE_MAIN_FILE', __FILE__ );
1617

1718
require_once __DIR__ . '/php-polyfills.php';

tests/WP_SQLite_Driver_Metadata_Tests.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-configurator.php';
34
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-driver.php';
45
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php';
56
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php';

tests/WP_SQLite_Driver_Query_Tests.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-configurator.php';
34
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-driver.php';
45
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php';
56
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php';

tests/WP_SQLite_Driver_Tests.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
require_once __DIR__ . '/WP_SQLite_Translator_Tests.php';
4+
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-configurator.php';
45
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-driver.php';
56
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php';
67
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php';

tests/WP_SQLite_Driver_Translation_Tests.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-configurator.php';
34
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-driver.php';
45
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php';
56
require_once __DIR__ . '/../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php';

tests/bootstrap.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
require_once __DIR__ . '/../wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php';
1515
require_once __DIR__ . '/../wp-includes/sqlite/class-wp-sqlite-translator.php';
1616

17+
/*
18+
* The driver version needs to be defined and set to anything other than "0.0.0"
19+
* for the tests, so that the information schema and other tables are created.
20+
*/
21+
define( 'SQLITE_DRIVER_VERSION', '2.0.0-tests' );
22+
1723
/**
1824
* Polyfills for WordPress functions
1925
*/

tests/tools/dump-sqlite-query.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
require_once __DIR__ . '/../../wp-includes/mysql/class-wp-mysql-token.php';
99
require_once __DIR__ . '/../../wp-includes/mysql/class-wp-mysql-parser.php';
1010
require_once __DIR__ . '/../../wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php';
11+
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-configurator.php';
1112
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver.php';
1213
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php';
1314
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php';
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
3+
/**
4+
* SQLite database configurator.
5+
*
6+
* This class initializes and configures the SQLite database, so that it can be
7+
* used by the SQLite driver to translate and emulate MySQL queries in SQLite.
8+
*
9+
* The configurator ensures that tables required for emulating MySQL behaviors
10+
* are created and populated with necessary data. It is also able to partially
11+
* repair and update these tables and metadata in case of database corruption.
12+
*/
13+
class WP_SQLite_Configurator {
14+
/**
15+
* The SQLite driver instance.
16+
*
17+
* @var WP_SQLite_Driver
18+
*/
19+
private $driver;
20+
21+
/**
22+
* A service for managing MySQL INFORMATION_SCHEMA tables in SQLite.
23+
*
24+
* @var WP_SQLite_Information_Schema_Builder
25+
*/
26+
private $information_schema_builder;
27+
28+
/**
29+
* Constructor.
30+
*
31+
* @param WP_SQLite_Driver $driver The SQLite driver instance.
32+
* @param WP_SQLite_Information_Schema_Builder $information_schema_builder The information schema builder instance.
33+
*/
34+
public function __construct(
35+
WP_SQLite_Driver $driver,
36+
WP_SQLite_Information_Schema_Builder $information_schema_builder
37+
) {
38+
$this->driver = $driver;
39+
$this->information_schema_builder = $information_schema_builder;
40+
}
41+
42+
/**
43+
* Ensure that the SQLite database is configured.
44+
*
45+
* This method checks if the database is configured for the latest SQLite
46+
* driver version, and if it is not, it will configure the database.
47+
*/
48+
public function ensure_database_configured(): void {
49+
$version = SQLITE_DRIVER_VERSION;
50+
$db_version = $this->driver->get_saved_driver_version();
51+
if ( version_compare( $version, $db_version ) > 0 ) {
52+
$this->configure_database();
53+
}
54+
}
55+
56+
/**
57+
* Configure the SQLite database.
58+
*
59+
* This method creates tables used for emulating MySQL behaviors in SQLite,
60+
* and populates them with necessary data. When it is used with an already
61+
* configured database, it will update the configuration as per the current
62+
* SQLite driver version and attempt to repair any configuration corruption.
63+
*/
64+
public function configure_database(): void {
65+
$this->ensure_global_variables_table();
66+
$this->information_schema_builder->ensure_information_schema_tables();
67+
$this->save_current_driver_version();
68+
}
69+
70+
/**
71+
* Ensure that the global variables table exists.
72+
*
73+
* This method configures a database table to store MySQL global variables
74+
* and other internal configuration values.
75+
*/
76+
private function ensure_global_variables_table(): void {
77+
$this->driver->execute_sqlite_query(
78+
sprintf(
79+
'CREATE TABLE IF NOT EXISTS %s (name TEXT PRIMARY KEY, value TEXT)',
80+
WP_SQLite_Driver::GLOBAL_VARIABLES_TABLE_NAME
81+
)
82+
);
83+
}
84+
85+
/**
86+
* Save the current SQLite driver version.
87+
*
88+
* This method saves the current SQLite driver version to the database.
89+
*/
90+
private function save_current_driver_version(): void {
91+
$this->driver->execute_sqlite_query(
92+
sprintf(
93+
'INSERT INTO %s (name, value) VALUES (?, ?) ON CONFLICT(name) DO UPDATE SET value = ?',
94+
WP_SQLite_Driver::GLOBAL_VARIABLES_TABLE_NAME
95+
),
96+
array(
97+
WP_SQLite_Driver::DRIVER_VERSION_VARIABLE_NAME,
98+
SQLITE_DRIVER_VERSION,
99+
SQLITE_DRIVER_VERSION,
100+
)
101+
);
102+
}
103+
}

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

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,22 @@ class WP_SQLite_Driver {
4040
*/
4141
const RESERVED_PREFIX = '_wp_sqlite_';
4242

43+
/**
44+
* The name of a global variables table.
45+
*
46+
* This special table is used to emulate MySQL global variables and to store
47+
* some internal configuration values.
48+
*/
49+
const GLOBAL_VARIABLES_TABLE_NAME = self::RESERVED_PREFIX . 'global_variables';
50+
51+
/**
52+
* The name of the SQLite driver version variable.
53+
*
54+
* This internal variable is used to store the latest version of the SQLite
55+
* driver that was used to initialize and configure the SQLite database.
56+
*/
57+
const DRIVER_VERSION_VARIABLE_NAME = self::RESERVED_PREFIX . 'driver_version';
58+
4359
/**
4460
* A map of MySQL tokens to SQLite data types.
4561
*
@@ -524,7 +540,10 @@ public function __construct( array $options ) {
524540
self::RESERVED_PREFIX,
525541
array( $this, 'execute_sqlite_query' )
526542
);
527-
$this->information_schema_builder->ensure_information_schema_tables();
543+
544+
// Ensure that the database is configured.
545+
$migrator = new WP_SQLite_Configurator( $this, $this->information_schema_builder );
546+
$migrator->ensure_database_configured();
528547
}
529548

530549
/**
@@ -545,6 +564,31 @@ public function get_sqlite_version(): string {
545564
return $this->pdo->query( 'SELECT SQLITE_VERSION()' )->fetchColumn();
546565
}
547566

567+
/**
568+
* Get the SQLite driver version saved in the database.
569+
*
570+
* The saved driver version corresponds to the latest version of the SQLite
571+
* driver that was used to initialize and configure the SQLite database.
572+
*
573+
* @return string SQLite driver version as a string.
574+
* @throws PDOException When the query execution fails.
575+
*/
576+
public function get_saved_driver_version(): string {
577+
$default_version = '0.0.0';
578+
try {
579+
$stmt = $this->execute_sqlite_query(
580+
sprintf( 'SELECT value FROM %s WHERE name = ?', self::GLOBAL_VARIABLES_TABLE_NAME ),
581+
array( self::DRIVER_VERSION_VARIABLE_NAME )
582+
);
583+
return $stmt->fetchColumn() ?? $default_version;
584+
} catch ( PDOException $e ) {
585+
if ( str_contains( $e->getMessage(), 'no such table' ) ) {
586+
return $default_version;
587+
}
588+
throw $e;
589+
}
590+
}
591+
548592
/**
549593
* Check if a specific SQL mode is active.
550594
*

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ public function db_connect( $allow_bail = true ) {
300300
require_once __DIR__ . '/../../wp-includes/mysql/class-wp-mysql-token.php';
301301
require_once __DIR__ . '/../../wp-includes/mysql/class-wp-mysql-lexer.php';
302302
require_once __DIR__ . '/../../wp-includes/mysql/class-wp-mysql-parser.php';
303+
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-configurator.php';
303304
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver.php';
304305
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php';
305306
require_once __DIR__ . '/../../wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php';

0 commit comments

Comments
 (0)