Skip to content

Database configuration and migration #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 37 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6a641f9
Implement a database configurator service for DB initialization and m…
JanJakes Apr 15, 2025
12d3063
Implement more robust plugin version definition and CI check
JanJakes Apr 15, 2025
9a6da9d
Load AST classes for tests in test bootstrap
JanJakes Apr 16, 2025
7727cfa
Implement information schema reconstructor
JanJakes Apr 16, 2025
23331b3
Reconstruct WordPress tables using "wp_get_db_schema" function
JanJakes Apr 17, 2025
ed959fb
Avoid race conditions when configuring the SQLite database
JanJakes Apr 17, 2025
287f4f4
Improve docs
JanJakes Apr 22, 2025
907be69
Fix identifier unquoting
JanJakes Apr 22, 2025
b178b97
In WordPress, make sure the "wp_get_db_schema()" function is defined
JanJakes Apr 22, 2025
5edd7f7
Filter out reserved tables using LIKE
JanJakes Apr 22, 2025
5dddd50
Improve the clarity of primary key reconstruction
JanJakes Apr 22, 2025
95b1a19
Document SQLite column affinity inline
JanJakes Apr 22, 2025
51b22fa
Do not acquire an exclusive lock for every version check, lock only c…
JanJakes Apr 22, 2025
d904064
Fix $wpdb dependency loop when using schema reconstructor in WP
JanJakes Apr 23, 2025
69381d8
Add support for multi-query parsing
JanJakes Apr 23, 2025
cde7da8
Store and expose byte start and length in tokens and nodes
JanJakes Apr 23, 2025
0283884
Parse queries from "wp_get_db_schema()"
JanJakes Apr 23, 2025
e657ad0
Pass input in tokens and get token values lazily
JanJakes Apr 23, 2025
30c8212
Move multi-query parsing to WP_MySQL_Parser, improve naming and docs
JanJakes Apr 23, 2025
6a3b370
Return parser instance rather than a generator
JanJakes Apr 23, 2025
1121fcc
Refactor and document key column definition inference
JanJakes Apr 24, 2025
231bab2
Refactor and document key definition inference
JanJakes Apr 24, 2025
be2841d
Improve and document default column value detection
JanJakes Apr 24, 2025
fd55809
Extract WP schema to a method, improve naming and docs
JanJakes Apr 25, 2025
baa22c3
For multisite installs, reconstruct WP schema for all sites
JanJakes Apr 25, 2025
c67f6c4
Refactor default value handling, add escaping and tests
JanJakes Apr 25, 2025
959505e
Fix schema inference for WordPress tables
JanJakes Apr 25, 2025
d1dfd2c
Fix removing schema records for non-existent tables
JanJakes Apr 25, 2025
859fb9f
Improve CI job name
JanJakes Apr 27, 2025
94e582c
Always quote identifiers in driver and reconstructor
JanJakes Apr 28, 2025
b0009d6
Extract SQLite connection management to WP_SQLite_Connection
JanJakes Apr 28, 2025
1d284e6
Consolidate SQLite identifier escaping in WP_SQLite_Connection, impro…
JanJakes Apr 28, 2025
4df273e
Fix and refactor test setup
JanJakes Apr 29, 2025
838967a
Always quote identifiers in information schema builder
JanJakes Apr 29, 2025
c745a66
Unify quoting also for $wpdb->blogs table name
JanJakes Apr 29, 2025
9b21ab3
Fix parser API, explicitly disable multi-queries in WP_SQLite_Driver:…
JanJakes Apr 29, 2025
5004c07
Fix and improve default value formatting
JanJakes Apr 30, 2025
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
35 changes: 35 additions & 0 deletions .github/workflows/verify-version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Verify plugin version

on:
push:
branches:
- main
pull_request:

jobs:
verify-version:
name: Assert the WordPress plugin header declares the same version as the SQLITE_DRIVER_VERSION constant
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Extract version from "load.php"
id: load_version
run: |
VERSION=$(grep "Version:" load.php | sed "s/.*Version: \([^ ]*\).*/\1/")
echo "load_version=$VERSION" >> $GITHUB_OUTPUT

- name: Extract version from "version.php"
id: const_version
run: |
VERSION=$(php -r "require 'version.php'; echo SQLITE_DRIVER_VERSION;")
echo "const_version=$VERSION" >> $GITHUB_OUTPUT

- name: Compare versions
run: |
if [ "${{ steps.load_version.outputs.load_version }}" != "${{ steps.const_version.outputs.const_version }}" ]; then
echo "Version mismatch detected!"
echo " load.php version: ${{ steps.load_version.outputs.load_version }}"
echo " version.php constant: ${{ steps.const_version.outputs.const_version }}"
exit 1
fi
6 changes: 6 additions & 0 deletions load.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
* @package wp-sqlite-integration
*/

/**
* Load the "SQLITE_DRIVER_VERSION" constant.
* This constant needs to be updated on plugin release!
*/
require_once __DIR__ . '/version.php';

define( 'SQLITE_MAIN_FILE', __FILE__ );

require_once __DIR__ . '/php-polyfills.php';
Expand Down
34 changes: 5 additions & 29 deletions tests/WP_SQLite_Driver_Metadata_Tests.php
Original file line number Diff line number Diff line change
@@ -1,44 +1,20 @@
<?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';

use PHPUnit\Framework\TestCase;

class WP_SQLite_Driver_Metadata_Tests extends TestCase {

/** @var WP_SQLite_Driver */
private $engine;
private $sqlite;

public static function setUpBeforeClass(): void {
// if ( ! defined( 'PDO_DEBUG' )) {
// define( 'PDO_DEBUG', true );
// }
if ( ! defined( 'FQDB' ) ) {
define( 'FQDB', ':memory:' );
define( 'FQDBDIR', __DIR__ . '/../testdb' );
}
error_reporting( E_ALL & ~E_DEPRECATED );
if ( ! isset( $GLOBALS['table_prefix'] ) ) {
$GLOBALS['table_prefix'] = 'wptests_';
}
if ( ! isset( $GLOBALS['wpdb'] ) ) {
$GLOBALS['wpdb'] = new stdClass();
$GLOBALS['wpdb']->suppress_errors = false;
$GLOBALS['wpdb']->show_errors = true;
}
return;
}
/** @var PDO */
private $sqlite;

// Before each test, we create a new database
public function setUp(): void {
$this->sqlite = new PDO( 'sqlite::memory:' );
$this->engine = new WP_SQLite_Driver(
array(
'connection' => $this->sqlite,
'database' => 'wp',
)
new WP_SQLite_Connection( array( 'pdo' => $this->sqlite ) ),
'wp'
);
}

Expand Down
38 changes: 7 additions & 31 deletions tests/WP_SQLite_Driver_Query_Tests.php
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
<?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';

use PHPUnit\Framework\TestCase;

/**
* Unit tests using the WordPress table definitions.
*/
class WP_SQLite_Driver_Query_Tests extends TestCase {

/** @var WP_SQLite_Driver */
private $engine;
private $sqlite;

public static function setUpBeforeClass(): void {
// if ( ! defined( 'PDO_DEBUG' )) {
// define( 'PDO_DEBUG', true );
// }
if ( ! defined( 'FQDB' ) ) {
define( 'FQDB', ':memory:' );
define( 'FQDBDIR', __DIR__ . '/../testdb' );
}
error_reporting( E_ALL & ~E_DEPRECATED );
if ( ! isset( $GLOBALS['table_prefix'] ) ) {
$GLOBALS['table_prefix'] = 'wptests_';
}
if ( ! isset( $GLOBALS['wpdb'] ) ) {
$GLOBALS['wpdb'] = new stdClass();
$GLOBALS['wpdb']->suppress_errors = false;
$GLOBALS['wpdb']->show_errors = true;
}
return;
}
/** @var PDO */
private $sqlite;

/**
* Before each test, we create a new volatile database and WordPress tables.
Expand All @@ -47,10 +25,8 @@ public function setUp(): void {

$this->sqlite = new PDO( 'sqlite::memory:' );
$this->engine = new WP_SQLite_Driver(
array(
'connection' => $this->sqlite,
'database' => 'wp',
)
new WP_SQLite_Connection( array( 'pdo' => $this->sqlite ) ),
'wp'
);

$translator = $this->engine;
Expand Down Expand Up @@ -462,7 +438,7 @@ public function testRecoverSerialized() {
);
$option_name = 'serialized_option';
$option_value = serialize( $obj );
$option_value_escaped = $this->engine->get_pdo()->quote( $option_value );
$option_value_escaped = $this->engine->get_connection()->quote( $option_value );
/* Note well: this is heredoc not nowdoc */
$insert = <<<QUERY
INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`)
Expand All @@ -488,7 +464,7 @@ public function testRecoverSerialized() {
++$obj ['two'];
$obj ['pi'] *= 2;
$option_value = serialize( $obj );
$option_value_escaped = $this->engine->get_pdo()->quote( $option_value );
$option_value_escaped = $this->engine->get_connection()->quote( $option_value );
/* Note well: this is heredoc not nowdoc */
$insert = <<<QUERY
INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`)
Expand Down
45 changes: 13 additions & 32 deletions tests/WP_SQLite_Driver_Tests.php
Original file line number Diff line number Diff line change
@@ -1,46 +1,21 @@
<?php

require_once __DIR__ . '/WP_SQLite_Translator_Tests.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';

use PHPUnit\Framework\TestCase;

class WP_SQLite_Driver_Tests extends TestCase {

/** @var WP_SQLite_Driver */
private $engine;
private $sqlite;

public static function setUpBeforeClass(): void {
// if ( ! defined( 'PDO_DEBUG' )) {
// define( 'PDO_DEBUG', true );
// }
if ( ! defined( 'FQDB' ) ) {
define( 'FQDB', ':memory:' );
define( 'FQDBDIR', __DIR__ . '/../testdb' );
}
error_reporting( E_ALL & ~E_DEPRECATED );
if ( ! isset( $GLOBALS['table_prefix'] ) ) {
$GLOBALS['table_prefix'] = 'wptests_';
}
if ( ! isset( $GLOBALS['wpdb'] ) ) {
$GLOBALS['wpdb'] = new stdClass();
$GLOBALS['wpdb']->suppress_errors = false;
$GLOBALS['wpdb']->show_errors = true;
}
return;
}
/** @var PDO */
private $sqlite;

// Before each test, we create a new database
public function setUp(): void {
$this->sqlite = new PDO( 'sqlite::memory:' );

$this->engine = new WP_SQLite_Driver(
array(
'connection' => $this->sqlite,
'database' => 'wp',
)
new WP_SQLite_Connection( array( 'pdo' => $this->sqlite ) ),
'wp'
);
$this->engine->query(
"CREATE TABLE _options (
Expand Down Expand Up @@ -1234,14 +1209,14 @@ public function testColumnWithOnUpdate() {
'name' => '_wp_sqlite__tmp_table_created_at_on_update',
'tbl_name' => '_tmp_table',
'rootpage' => '0',
'sql' => "CREATE TRIGGER \"_wp_sqlite__tmp_table_created_at_on_update\"\n\t\t\tAFTER UPDATE ON \"_tmp_table\"\n\t\t\tFOR EACH ROW\n\t\t\tBEGIN\n\t\t\t UPDATE \"_tmp_table\" SET \"created_at\" = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;\n\t\t\tEND",
'sql' => "CREATE TRIGGER `_wp_sqlite__tmp_table_created_at_on_update`\n\t\t\t\tAFTER UPDATE ON `_tmp_table`\n\t\t\t\tFOR EACH ROW\n\t\t\t\tBEGIN\n\t\t\t\t UPDATE `_tmp_table` SET `created_at` = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;\n\t\t\t\tEND",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit – how about heredoc or nowdoc to make it a bit more readable for humans?

),
(object) array(
'type' => 'trigger',
'name' => '_wp_sqlite__tmp_table_updated_at_on_update',
'tbl_name' => '_tmp_table',
'rootpage' => '0',
'sql' => "CREATE TRIGGER \"_wp_sqlite__tmp_table_updated_at_on_update\"\n\t\t\tAFTER UPDATE ON \"_tmp_table\"\n\t\t\tFOR EACH ROW\n\t\t\tBEGIN\n\t\t\t UPDATE \"_tmp_table\" SET \"updated_at\" = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;\n\t\t\tEND",
'sql' => "CREATE TRIGGER `_wp_sqlite__tmp_table_updated_at_on_update`\n\t\t\t\tAFTER UPDATE ON `_tmp_table`\n\t\t\t\tFOR EACH ROW\n\t\t\t\tBEGIN\n\t\t\t\t UPDATE `_tmp_table` SET `updated_at` = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;\n\t\t\t\tEND",
),
),
$results
Expand Down Expand Up @@ -4488,4 +4463,10 @@ public function testSessionSqlModes(): void {
$result = $this->assertQuery( 'SELECT @@session.SQL_mode' );
$this->assertSame( 'ONLY_FULL_GROUP_BY', $result[0]->{'@@session.SQL_mode'} );
}

public function testMultiQueryNotSupported(): void {
$this->expectException( WP_SQLite_Driver_Exception::class );
$this->expectExceptionMessage( 'Multi-query is not supported.' );
$this->assertQuery( 'SELECT 1; SELECT 2' );
}
}
Loading