From c5b9cd1d1f5fd6ebd5d52cdd611859ddd150ca43 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Wed, 25 Jun 2025 16:21:26 +0200 Subject: [PATCH 01/14] Add support for the new SQLite driver --- src/Export.php | 48 ++++++++++++++++++------- src/Import.php | 13 ++++--- src/SQLiteDatabaseIntegrationLoader.php | 31 +++++++++++++--- src/SQLiteDriverFactory.php | 30 ++++++++++++++++ src/Tables.php | 16 ++++++--- 5 files changed, 113 insertions(+), 25 deletions(-) create mode 100644 src/SQLiteDriverFactory.php diff --git a/src/Export.php b/src/Export.php index 32463c4..d69061d 100644 --- a/src/Export.php +++ b/src/Export.php @@ -4,17 +4,23 @@ use Exception; use PDO; use WP_CLI; +use WP_SQLite_Driver; use WP_SQLite_Translator; class Export { + /** + * The SQLite driver instance. + * + * @var WP_SQLite_Driver|WP_SQLite_Translator + */ + protected $driver; - protected $translator; protected $args = array(); protected $is_stdout = false; public function __construct() { SQLiteDatabaseIntegrationLoader::load_plugin(); - $this->translator = new WP_SQLite_Translator(); + $this->driver = SQLiteDriverFactory::create_driver(); } /** @@ -79,19 +85,21 @@ protected function close_output_stream( $handle ) { protected function write_sql_statements( $handle ) { $include_tables = $this->get_include_tables(); $exclude_tables = $this->get_exclude_tables(); - foreach ( $this->translator->query( 'SHOW TABLES' ) as $table ) { + foreach ( $this->driver->query( 'SHOW TABLES' ) as $row ) { + $table_name = array_values( (array) $row )[0]; + // Skip tables that are not in the include_tables list if the list is defined - if ( ! empty( $include_tables ) && ! in_array( $table->name, $include_tables, true ) ) { + if ( ! empty( $include_tables ) && ! in_array( $table_name, $include_tables, true ) ) { continue; } // Skip tables that are in the exclude_tables list - if ( in_array( $table->name, $exclude_tables, true ) ) { + if ( in_array( $table_name, $exclude_tables, true ) ) { continue; } - $this->write_create_table_statement( $handle, $table->name ); - $this->write_insert_statements( $handle, $table->name ); + $this->write_create_table_statement( $handle, $table_name ); + $this->write_insert_statements( $handle, $table_name ); } fwrite( $handle, sprintf( '-- Dump completed on %s', gmdate( 'c' ) ) ); @@ -144,8 +152,12 @@ protected function write_insert_statements( $handle, $table_name ) { * @throws Exception */ protected function get_create_statement( $table_name ) { - $create = $this->translator->query( 'SHOW CREATE TABLE ' . $table_name ); - return $create[0]->{'Create Table'} . "\n"; + $table_name = $this->driver instanceof WP_SQLite_Driver + ? $this->driver->get_connection()->quote_identifier( $table_name ) + : $table_name; + + $create = $this->driver->query( 'SHOW CREATE TABLE ' . $table_name ); + return $create[0]->{'Create Table'} . ";\n"; } /** @@ -156,7 +168,7 @@ protected function get_create_statement( $table_name ) { * @return \Generator */ protected function get_insert_statements( $table_name ) { - $pdo = $this->translator->get_pdo(); + $pdo = $this->get_pdo(); $stmt = $pdo->prepare( 'SELECT * FROM ' . $table_name ); $stmt->execute(); // phpcs:ignore @@ -235,7 +247,7 @@ protected function escape_values( PDO $pdo, $values ) { * @return string */ protected function escape_string( $value ) { - $pdo = $this->translator->get_pdo(); + $pdo = $this->get_pdo(); return addcslashes( $pdo->quote( $value ), "\\\n" ); } @@ -261,9 +273,21 @@ protected function get_dump_comment( $comment ) { * @return bool */ protected function table_has_records( $table_name ) { - $pdo = $this->translator->get_pdo(); + $pdo = $this->get_pdo(); $stmt = $pdo->prepare( 'SELECT COUNT(*) FROM ' . $table_name ); $stmt->execute(); return $stmt->fetchColumn() > 0; } + + /** + * Get the PDO instance. + * + * @return PDO + */ + protected function get_pdo() { + if ( $this->driver instanceof WP_SQLite_Translator ) { + return $this->driver->get_pdo(); + } + return $this->driver->get_connection()->get_pdo(); + } } diff --git a/src/Import.php b/src/Import.php index de33441..d9aa644 100644 --- a/src/Import.php +++ b/src/Import.php @@ -7,13 +7,18 @@ use WP_SQLite_Translator; class Import { + /** + * The SQLite driver instance. + * + * @var WP_SQLite_Driver|WP_SQLite_Translator + */ + protected $driver; - protected $translator; protected $args; public function __construct() { SQLiteDatabaseIntegrationLoader::load_plugin(); - $this->translator = new WP_SQLite_Translator(); + $this->driver = SQLiteDriverFactory::create_driver(); } /** @@ -46,10 +51,10 @@ public function run( $sql_file_path, $args ) { */ protected function execute_statements( $import_file ) { foreach ( $this->parse_statements( $import_file ) as $statement ) { - $result = $this->translator->query( $statement ); + $result = $this->driver->query( $statement ); if ( false === $result ) { WP_CLI::warning( 'Could not execute statement: ' . $statement ); - echo $this->translator->get_error_message(); + echo $this->driver->get_error_message(); } } } diff --git a/src/SQLiteDatabaseIntegrationLoader.php b/src/SQLiteDatabaseIntegrationLoader.php index 4c75bde..f5259ca 100644 --- a/src/SQLiteDatabaseIntegrationLoader.php +++ b/src/SQLiteDatabaseIntegrationLoader.php @@ -85,10 +85,31 @@ public static function load_plugin() { // We also need to selectively load the necessary classes from the plugin. require_once $plugin_directory . '/php-polyfills.php'; require_once $plugin_directory . '/constants.php'; - require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-lexer.php'; - require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-query-rewriter.php'; - require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-translator.php'; - require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-token.php'; - require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php'; + + $new_driver_supported = class_exists( WP_SQLite_Driver::class ); + $new_driver_enabled = $new_driver_supported && defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; + + if ( $new_driver_enabled ) { + require_once $plugin_directory . '/wp-includes/parser/class-wp-parser-grammar.php'; + require_once $plugin_directory . '/wp-includes/parser/class-wp-parser.php'; + require_once $plugin_directory . '/wp-includes/parser/class-wp-parser-node.php'; + require_once $plugin_directory . '/wp-includes/parser/class-wp-parser-token.php'; + require_once $plugin_directory . '/wp-includes/mysql/class-wp-mysql-token.php'; + require_once $plugin_directory . '/wp-includes/mysql/class-wp-mysql-lexer.php'; + require_once $plugin_directory . '/wp-includes/mysql/class-wp-mysql-parser.php'; + require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-connection.php'; + require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-configurator.php'; + require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-driver.php'; + require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-driver-exception.php'; + require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php'; + require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-exception.php'; + require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php'; + } else { + require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-lexer.php'; + require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-query-rewriter.php'; + require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-translator.php'; + require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-token.php'; + require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php'; + } } } diff --git a/src/SQLiteDriverFactory.php b/src/SQLiteDriverFactory.php new file mode 100644 index 0000000..420d757 --- /dev/null +++ b/src/SQLiteDriverFactory.php @@ -0,0 +1,30 @@ + FQDB, + ) + ); + return new WP_SQLite_Driver( $connection, DB_NAME ); + } + + return new WP_SQLite_Translator(); + } +} diff --git a/src/Tables.php b/src/Tables.php index 28bee0c..79a64ca 100644 --- a/src/Tables.php +++ b/src/Tables.php @@ -4,15 +4,20 @@ use WP_CLI; use PDO; +use WP_SQLite_Driver; use WP_SQLite_Translator; class Tables { - - protected $translator; + /** + * The SQLite driver instance. + * + * @var WP_SQLite_Driver|WP_SQLite_Translator + */ + protected $driver; public function __construct() { SQLiteDatabaseIntegrationLoader::load_plugin(); - $this->translator = new WP_SQLite_Translator(); + $this->driver = SQLiteDriverFactory::create_driver(); } /** @@ -21,7 +26,10 @@ public function __construct() { * @return PDO */ protected function get_pdo() { - return $this->translator->get_pdo(); + if ( $this->driver instanceof WP_SQLite_Translator ) { + return $this->driver->get_pdo(); + } + return $this->driver->get_connection()->get_pdo(); } /** From db83ba27dfee281be53eb640b9a1c215efc703a3 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Wed, 25 Jun 2025 16:34:02 +0200 Subject: [PATCH 02/14] Use MySQL SHOW TABLES insteand of SQLite schema tables --- README.md | 12 ++++++------ features/sqlite_tables.feature | 16 ++++++++-------- src/Tables.php | 31 +++++++++++-------------------- 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index c1eb583..21f702c 100644 --- a/README.md +++ b/README.md @@ -66,18 +66,18 @@ $ wp sqlite tables [--format=] ``` # List all tables $ wp sqlite tables - wp_users - wp_usermeta - wp_termmeta - wp_terms - wp_term_taxonomy - wp_term_relationships wp_commentmeta wp_comments wp_links wp_options wp_postmeta wp_posts + wp_term_relationships + wp_term_taxonomy + wp_termmeta + wp_terms + wp_usermeta + wp_users * List all tables in CSV format $ wp sqlite tables --format=csv diff --git a/features/sqlite_tables.feature b/features/sqlite_tables.feature index e3527f6..adeb395 100644 --- a/features/sqlite_tables.feature +++ b/features/sqlite_tables.feature @@ -11,18 +11,18 @@ Feature: WP-CLI SQLite Tables Command When I run `wp sqlite tables` Then STDOUT should contain: """ - wp_users - wp_usermeta - wp_termmeta - wp_terms - wp_term_taxonomy - wp_term_relationships wp_commentmeta wp_comments wp_links wp_options wp_postmeta wp_posts + wp_term_relationships + wp_term_taxonomy + wp_termmeta + wp_terms + wp_usermeta + wp_users """ @require-sqlite @@ -30,7 +30,7 @@ Feature: WP-CLI SQLite Tables Command When I run `wp sqlite tables --format=csv` Then STDOUT should contain: """ - wp_users,wp_usermeta,wp_termmeta,wp_terms,wp_term_taxonomy,wp_term_relationships,wp_commentmeta,wp_comments,wp_links,wp_options,wp_postmeta,wp_posts + wp_commentmeta,wp_comments,wp_links,wp_options,wp_postmeta,wp_posts,wp_term_relationships,wp_term_taxonomy,wp_termmeta,wp_terms,wp_usermeta,wp_users """ @require-sqlite @@ -38,5 +38,5 @@ Feature: WP-CLI SQLite Tables Command When I run `wp sqlite tables --format=json` Then STDOUT should contain: """ - ["wp_users","wp_usermeta","wp_termmeta","wp_terms","wp_term_taxonomy","wp_term_relationships","wp_commentmeta","wp_comments","wp_links","wp_options","wp_postmeta","wp_posts"] + ["wp_commentmeta","wp_comments","wp_links","wp_options","wp_postmeta","wp_posts","wp_term_relationships","wp_term_taxonomy","wp_termmeta","wp_terms","wp_usermeta","wp_users"] """ diff --git a/src/Tables.php b/src/Tables.php index 79a64ca..451897d 100644 --- a/src/Tables.php +++ b/src/Tables.php @@ -3,7 +3,6 @@ namespace Automattic\WP_CLI\SQLite; use WP_CLI; -use PDO; use WP_SQLite_Driver; use WP_SQLite_Translator; @@ -20,18 +19,6 @@ public function __construct() { $this->driver = SQLiteDriverFactory::create_driver(); } - /** - * Get the PDO instance. - * - * @return PDO - */ - protected function get_pdo() { - if ( $this->driver instanceof WP_SQLite_Translator ) { - return $this->driver->get_pdo(); - } - return $this->driver->get_connection()->get_pdo(); - } - /** * Lists all tables in the SQLite database. * @@ -39,15 +26,19 @@ protected function get_pdo() { * @return void */ public function run( $assoc_args = [] ) { - $pdo = $this->get_pdo(); - // Get all tables - $stmt = $pdo->query( "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'" ); - $tables = $stmt->fetchAll( PDO::FETCH_COLUMN ); + $tables = array(); + foreach ( $this->driver->query( 'SHOW TABLES' ) as $row ) { + $tables[] = array_values( (array) $row )[0]; + } - // Remove system tables - $tables_to_exclude = array( '_mysql_data_types_cache' ); - $tables = array_diff( $tables, $tables_to_exclude ); + // With the legacy driver, we need to exclude system tables + // and make sure the table names are alphabetically sorted. + if ( $this->driver instanceof WP_SQLite_Translator ) { + $tables_to_exclude = array( '_mysql_data_types_cache', 'sqlite_sequence' ); + $tables = array_diff( $tables, $tables_to_exclude ); + sort( $tables ); + } if ( empty( $tables ) ) { WP_CLI::error( 'No tables found in the database.' ); From 275b3827aab0eef83e968904c4d0962e1e3cb6b2 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Wed, 25 Jun 2025 17:33:21 +0200 Subject: [PATCH 03/14] Fix linter errors --- features/pass.feature | 2 +- features/{sqlite_export.feature => sqlite-export.feature} | 0 features/{sqlite_import.feature => sqlite-import.feature} | 0 features/{sqlite_tables.feature => sqlite-tables.feature} | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename features/{sqlite_export.feature => sqlite-export.feature} (100%) rename features/{sqlite_import.feature => sqlite-import.feature} (100%) rename features/{sqlite_tables.feature => sqlite-tables.feature} (100%) diff --git a/features/pass.feature b/features/pass.feature index 8d63855..9efcd38 100644 --- a/features/pass.feature +++ b/features/pass.feature @@ -1,5 +1,5 @@ Feature: Always Passing Test - Scenario: Evaluate true expression + Scenario: Evaluate true expression Given a WP install When I run `wp eval "var_export(true);"` diff --git a/features/sqlite_export.feature b/features/sqlite-export.feature similarity index 100% rename from features/sqlite_export.feature rename to features/sqlite-export.feature diff --git a/features/sqlite_import.feature b/features/sqlite-import.feature similarity index 100% rename from features/sqlite_import.feature rename to features/sqlite-import.feature diff --git a/features/sqlite_tables.feature b/features/sqlite-tables.feature similarity index 100% rename from features/sqlite_tables.feature rename to features/sqlite-tables.feature From 8ee70fb63d5de90026848827576f6e54f2986060 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Thu, 26 Jun 2025 15:59:38 +0200 Subject: [PATCH 04/14] Ensure CREATE TABLE statements are terminated with a single semicolon --- src/Export.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Export.php b/src/Export.php index d69061d..4594860 100644 --- a/src/Export.php +++ b/src/Export.php @@ -157,7 +157,9 @@ protected function get_create_statement( $table_name ) { : $table_name; $create = $this->driver->query( 'SHOW CREATE TABLE ' . $table_name ); - return $create[0]->{'Create Table'} . ";\n"; + $sql = $create[0]->{'Create Table'}; + $sql = rtrim( $sql, ';' ); // The old SQLite driver appends a semicolon. + return $sql . ";\n"; } /** From 0ac5622b4419d2689d593e79903c11daa1f74cc2 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Thu, 26 Jun 2025 16:00:40 +0200 Subject: [PATCH 05/14] Explicitly exclude internal tables used by the new driver --- src/Export.php | 8 ++++++++ src/Tables.php | 10 ++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Export.php b/src/Export.php index 4594860..4273487 100644 --- a/src/Export.php +++ b/src/Export.php @@ -93,6 +93,12 @@ protected function write_sql_statements( $handle ) { continue; } + // Skip internal tables used by the new SQLite driver + // (This is only needed when exporting with the legacy driver.) + if ( 0 === strpos( $table_name, '_wp_sqlite_' ) ) { + continue; + } + // Skip tables that are in the exclude_tables list if ( in_array( $table_name, $exclude_tables, true ) ) { continue; @@ -189,6 +195,8 @@ protected function get_exclude_tables() { return array_merge( $exclude_tables, [ + // This list is only needed when exporting with the legacy driver. + // In the new SQLite driver, SHOW TABLES never returns these tables. '_mysql_data_types_cache', 'sqlite_master', 'sqlite_sequence', diff --git a/src/Tables.php b/src/Tables.php index 451897d..bb67492 100644 --- a/src/Tables.php +++ b/src/Tables.php @@ -36,7 +36,13 @@ public function run( $assoc_args = [] ) { // and make sure the table names are alphabetically sorted. if ( $this->driver instanceof WP_SQLite_Translator ) { $tables_to_exclude = array( '_mysql_data_types_cache', 'sqlite_sequence' ); - $tables = array_diff( $tables, $tables_to_exclude ); + foreach ( $tables as $table ) { + if ( 0 === strpos( $table, '_wp_sqlite_' ) ) { + $tables_to_exclude[] = $table; + } + } + + $tables = array_values( array_diff( $tables, $tables_to_exclude ) ); sort( $tables ); } @@ -49,7 +55,7 @@ public function run( $assoc_args = [] ) { if ( 'csv' === $format ) { WP_CLI::line( implode( ',', $tables ) ); } elseif ( 'json' === $format ) { - WP_CLI::line( json_encode( array_values( $tables ) ) ); + WP_CLI::line( json_encode( $tables ) ); } else { foreach ( $tables as $table ) { WP_CLI::line( $table ); From b125d21678f98ea3a4cdf7b255ef1c8293eefecf Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Thu, 26 Jun 2025 16:00:56 +0200 Subject: [PATCH 06/14] Add missing file imports --- src/SQLiteDatabaseIntegrationLoader.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SQLiteDatabaseIntegrationLoader.php b/src/SQLiteDatabaseIntegrationLoader.php index f5259ca..33ea26c 100644 --- a/src/SQLiteDatabaseIntegrationLoader.php +++ b/src/SQLiteDatabaseIntegrationLoader.php @@ -90,6 +90,7 @@ public static function load_plugin() { $new_driver_enabled = $new_driver_supported && defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; if ( $new_driver_enabled ) { + require_once $plugin_directory . '/version.php'; require_once $plugin_directory . '/wp-includes/parser/class-wp-parser-grammar.php'; require_once $plugin_directory . '/wp-includes/parser/class-wp-parser.php'; require_once $plugin_directory . '/wp-includes/parser/class-wp-parser-node.php'; @@ -97,6 +98,7 @@ public static function load_plugin() { require_once $plugin_directory . '/wp-includes/mysql/class-wp-mysql-token.php'; require_once $plugin_directory . '/wp-includes/mysql/class-wp-mysql-lexer.php'; require_once $plugin_directory . '/wp-includes/mysql/class-wp-mysql-parser.php'; + require_once $plugin_directory . '/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php'; require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-connection.php'; require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-configurator.php'; require_once $plugin_directory . '/wp-includes/sqlite-ast/class-wp-sqlite-driver.php'; From f2ea941e1814e27f3c744ffe72f9d55334ee6240 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Tue, 1 Jul 2025 15:20:05 +0200 Subject: [PATCH 07/14] Execute "wp sqlite import" on "after_wp_config_load" --- src/SQLite_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SQLite_Command.php b/src/SQLite_Command.php index 85d025f..41253f2 100644 --- a/src/SQLite_Command.php +++ b/src/SQLite_Command.php @@ -21,7 +21,7 @@ class SQLite_Command extends WP_CLI_Command { * $ wp sqlite import wordpress_dbase.sql * Success: Imported from 'import wordpress_dbase.sql'. * - * @when before_wp_load + * @when after_wp_config_load */ public function import( $args, $assoc_args ) { From b62649ccdfeb92d930bf947214e41555c4bb8a6c Mon Sep 17 00:00:00 2001 From: Wojtek Naruniec Date: Wed, 2 Jul 2025 16:03:52 +0200 Subject: [PATCH 08/14] Move export command to after wp config load to access db name --- src/SQLite_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SQLite_Command.php b/src/SQLite_Command.php index 41253f2..03df2d0 100644 --- a/src/SQLite_Command.php +++ b/src/SQLite_Command.php @@ -72,7 +72,7 @@ public function import( $args, $assoc_args ) { * $ wp sqlite export --exclude_tables=wp_posts,wp_users * Success: Exported to 'wordpress_dbase.sql'. * - * @when before_wp_load + * @when after_wp_config_load */ public function export( $args, $assoc_args ) { $is_porcelain = isset( $assoc_args['porcelain'] ); From 710c4be397a264ea1fa488381ea5cac01248446b Mon Sep 17 00:00:00 2001 From: Wojtek Naruniec Date: Wed, 2 Jul 2025 16:22:45 +0200 Subject: [PATCH 09/14] Add param allowing to enable AST driver --- README.md | 9 +++++++++ src/SQLite_Command.php | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 21f702c..efd261c 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,9 @@ $ wp sqlite import The path to the MySQL compatible dump file to import. When passing `-` as the file argument, the SQL commands are read from standard input. + [--enable-ast-driver] + Enables new AST driver for full MySQL compatibility. + ### wp sqlite export Exports an SQLite database to a MySQL compatible file. @@ -42,6 +45,9 @@ $ wp sqlite export [] [--tables=] [--exclude-tables] [--porcelain] [--porcelain] Output filename for the exported database. + [--enable-ast-driver] + Enables new AST driver for full MySQL compatibility. + ### wp sqlite tables Lists the SQLite database tables. @@ -61,6 +67,9 @@ $ wp sqlite tables [--format=] - csv --- + [--enable-ast-driver] + Enables new AST driver for full MySQL compatibility. + **EXAMPLES** ``` diff --git a/src/SQLite_Command.php b/src/SQLite_Command.php index 03df2d0..114dee6 100644 --- a/src/SQLite_Command.php +++ b/src/SQLite_Command.php @@ -16,6 +16,9 @@ class SQLite_Command extends WP_CLI_Command { * * : The name of the SQL file to import. If '-', then reads from STDIN. If omitted, it will look for '{dbname}.sql'. * + * [--enable-ast-driver] + * : Enables new AST driver for full MySQL compatibility. + * * ## EXAMPLES * # Import the database from a file * $ wp sqlite import wordpress_dbase.sql @@ -24,6 +27,13 @@ class SQLite_Command extends WP_CLI_Command { * @when after_wp_config_load */ public function import( $args, $assoc_args ) { + $enable_ast_driver = isset( $assoc_args['enable-ast-driver'] ); + + if ( $enable_ast_driver ) { + if ( ! defined( 'WP_SQLITE_AST_DRIVER' ) || ! WP_SQLITE_AST_DRIVER ) { + define( 'WP_SQLITE_AST_DRIVER', true ); + } + } if ( empty( $args[0] ) ) { WP_CLI::error( 'Please provide a file to import.' ); @@ -52,6 +62,9 @@ public function import( $args, $assoc_args ) { * [--porcelain] * : Output filename for the exported database. * + * [--enable-ast-driver] + * : Enables new AST driver for full MySQL compatibility. + * * ## EXAMPLES * # Export the database to a file * $ wp sqlite export wordpress_dbase.sql @@ -75,11 +88,19 @@ public function import( $args, $assoc_args ) { * @when after_wp_config_load */ public function export( $args, $assoc_args ) { - $is_porcelain = isset( $assoc_args['porcelain'] ); + $is_porcelain = isset( $assoc_args['porcelain'] ); + $enable_ast_driver = isset( $assoc_args['enable-ast-driver'] ); + + if ( $enable_ast_driver ) { + if ( ! defined( 'WP_SQLITE_AST_DRIVER' ) || ! WP_SQLITE_AST_DRIVER ) { + define( 'WP_SQLITE_AST_DRIVER', true ); + } + } if ( ! $is_porcelain ) { WP_CLI::success( 'Exporting database...' ); } + $export = new Export(); if ( ! empty( $args[0] ) ) { @@ -111,6 +132,9 @@ public function export( $args, $assoc_args ) { * - csv * --- * + * [--enable-ast-driver] + * : Enables new AST driver for full MySQL compatibility. + * * ## EXAMPLES * * # List all tables in the database @@ -131,6 +155,14 @@ public function export( $args, $assoc_args ) { * @when before_wp_load */ public function tables( $args, $assoc_args ) { + $enable_ast_driver = isset( $assoc_args['enable-ast-driver'] ); + + if ( $enable_ast_driver ) { + if ( ! defined( 'WP_SQLITE_AST_DRIVER' ) || ! WP_SQLITE_AST_DRIVER ) { + define( 'WP_SQLITE_AST_DRIVER', true ); + } + } + $tables = new Tables(); $tables->run( $assoc_args ); } From 134471c15b746973495a20f40374e2dd32e2e6e5 Mon Sep 17 00:00:00 2001 From: Wojtek Naruniec Date: Wed, 2 Jul 2025 16:42:01 +0200 Subject: [PATCH 10/14] Remove incorrect check for new_driver_supported --- src/SQLiteDatabaseIntegrationLoader.php | 3 +-- src/SQLiteDriverFactory.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/SQLiteDatabaseIntegrationLoader.php b/src/SQLiteDatabaseIntegrationLoader.php index 33ea26c..75859e8 100644 --- a/src/SQLiteDatabaseIntegrationLoader.php +++ b/src/SQLiteDatabaseIntegrationLoader.php @@ -86,8 +86,7 @@ public static function load_plugin() { require_once $plugin_directory . '/php-polyfills.php'; require_once $plugin_directory . '/constants.php'; - $new_driver_supported = class_exists( WP_SQLite_Driver::class ); - $new_driver_enabled = $new_driver_supported && defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; + $new_driver_enabled = defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; if ( $new_driver_enabled ) { require_once $plugin_directory . '/version.php'; diff --git a/src/SQLiteDriverFactory.php b/src/SQLiteDriverFactory.php index 420d757..61ba548 100644 --- a/src/SQLiteDriverFactory.php +++ b/src/SQLiteDriverFactory.php @@ -13,8 +13,7 @@ class SQLiteDriverFactory { * @return WP_SQLite_Driver|WP_SQLite_Translator */ public static function create_driver() { - $new_driver_supported = class_exists( WP_SQLite_Driver::class ); - $new_driver_enabled = $new_driver_supported && defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; + $new_driver_enabled = defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; if ( $new_driver_enabled ) { $connection = new WP_SQLite_Connection( From a0daac75a5a26d3b46e8249eb14788b3321cc86b Mon Sep 17 00:00:00 2001 From: Wojtek Naruniec Date: Wed, 2 Jul 2025 17:39:54 +0200 Subject: [PATCH 11/14] Fix empty space formatting --- src/SQLiteDatabaseIntegrationLoader.php | 2 +- src/SQLiteDriverFactory.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SQLiteDatabaseIntegrationLoader.php b/src/SQLiteDatabaseIntegrationLoader.php index 75859e8..8f72197 100644 --- a/src/SQLiteDatabaseIntegrationLoader.php +++ b/src/SQLiteDatabaseIntegrationLoader.php @@ -86,7 +86,7 @@ public static function load_plugin() { require_once $plugin_directory . '/php-polyfills.php'; require_once $plugin_directory . '/constants.php'; - $new_driver_enabled = defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; + $new_driver_enabled = defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; if ( $new_driver_enabled ) { require_once $plugin_directory . '/version.php'; diff --git a/src/SQLiteDriverFactory.php b/src/SQLiteDriverFactory.php index 61ba548..9cf3fb6 100644 --- a/src/SQLiteDriverFactory.php +++ b/src/SQLiteDriverFactory.php @@ -13,7 +13,7 @@ class SQLiteDriverFactory { * @return WP_SQLite_Driver|WP_SQLite_Translator */ public static function create_driver() { - $new_driver_enabled = defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; + $new_driver_enabled = defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER; if ( $new_driver_enabled ) { $connection = new WP_SQLite_Connection( From d8b0b68ba5b833026ec11b15d80ebf7cb796e1dc Mon Sep 17 00:00:00 2001 From: Wojtek Naruniec Date: Wed, 2 Jul 2025 17:47:20 +0200 Subject: [PATCH 12/14] Disable sniff that checks for constant prefix --- src/SQLite_Command.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/SQLite_Command.php b/src/SQLite_Command.php index 114dee6..c4b1a2f 100644 --- a/src/SQLite_Command.php +++ b/src/SQLite_Command.php @@ -31,7 +31,9 @@ public function import( $args, $assoc_args ) { if ( $enable_ast_driver ) { if ( ! defined( 'WP_SQLITE_AST_DRIVER' ) || ! WP_SQLITE_AST_DRIVER ) { + // @phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound define( 'WP_SQLITE_AST_DRIVER', true ); + // @phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound } } @@ -93,7 +95,9 @@ public function export( $args, $assoc_args ) { if ( $enable_ast_driver ) { if ( ! defined( 'WP_SQLITE_AST_DRIVER' ) || ! WP_SQLITE_AST_DRIVER ) { + // @phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound define( 'WP_SQLITE_AST_DRIVER', true ); + // @phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound } } @@ -159,7 +163,9 @@ public function tables( $args, $assoc_args ) { if ( $enable_ast_driver ) { if ( ! defined( 'WP_SQLITE_AST_DRIVER' ) || ! WP_SQLITE_AST_DRIVER ) { + // @phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound define( 'WP_SQLITE_AST_DRIVER', true ); + // @phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound } } From 91a50b4d8d012b0011790e9d6847f38041997ca1 Mon Sep 17 00:00:00 2001 From: Wojtek Naruniec Date: Fri, 4 Jul 2025 11:36:25 +0200 Subject: [PATCH 13/14] Move commands back to before_wp_load event --- src/SQLite_Command.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SQLite_Command.php b/src/SQLite_Command.php index c4b1a2f..0c632c7 100644 --- a/src/SQLite_Command.php +++ b/src/SQLite_Command.php @@ -24,7 +24,7 @@ class SQLite_Command extends WP_CLI_Command { * $ wp sqlite import wordpress_dbase.sql * Success: Imported from 'import wordpress_dbase.sql'. * - * @when after_wp_config_load + * @when before_wp_load */ public function import( $args, $assoc_args ) { $enable_ast_driver = isset( $assoc_args['enable-ast-driver'] ); @@ -87,7 +87,7 @@ public function import( $args, $assoc_args ) { * $ wp sqlite export --exclude_tables=wp_posts,wp_users * Success: Exported to 'wordpress_dbase.sql'. * - * @when after_wp_config_load + * @when before_wp_load */ public function export( $args, $assoc_args ) { $is_porcelain = isset( $assoc_args['porcelain'] ); From 957e06a236640d6e61a1d0436040e9f87a6419da Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Fri, 11 Jul 2025 11:46:16 +0200 Subject: [PATCH 14/14] Use "after_wp_config_load" for all SQLite commands This ensures the DB_NAME constant from "wp-config.php" is used, and aligns these commands with similar "wp db" commands. With https://github.com/WordPress/sqlite-database-integration/pull/213, the correctness of the database name will also be verified. --- src/SQLite_Command.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SQLite_Command.php b/src/SQLite_Command.php index 0c632c7..4e7e60e 100644 --- a/src/SQLite_Command.php +++ b/src/SQLite_Command.php @@ -24,7 +24,7 @@ class SQLite_Command extends WP_CLI_Command { * $ wp sqlite import wordpress_dbase.sql * Success: Imported from 'import wordpress_dbase.sql'. * - * @when before_wp_load + * @when after_wp_config_load */ public function import( $args, $assoc_args ) { $enable_ast_driver = isset( $assoc_args['enable-ast-driver'] ); @@ -87,7 +87,7 @@ public function import( $args, $assoc_args ) { * $ wp sqlite export --exclude_tables=wp_posts,wp_users * Success: Exported to 'wordpress_dbase.sql'. * - * @when before_wp_load + * @when after_wp_config_load */ public function export( $args, $assoc_args ) { $is_porcelain = isset( $assoc_args['porcelain'] ); @@ -156,7 +156,7 @@ public function export( $args, $assoc_args ) { * wp_usermeta * wp_users * - * @when before_wp_load + * @when after_wp_config_load */ public function tables( $args, $assoc_args ) { $enable_ast_driver = isset( $assoc_args['enable-ast-driver'] );