diff --git a/features/bootstrap/SQLiteFeatureContext.php b/features/bootstrap/SQLiteFeatureContext.php index 9a07975..b298fb2 100644 --- a/features/bootstrap/SQLiteFeatureContext.php +++ b/features/bootstrap/SQLiteFeatureContext.php @@ -3,7 +3,6 @@ namespace Automattic\WP_CLI\SQLite; use Behat\Behat\Context\Context; -use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Behat\Gherkin\Node\PyStringNode; use WP_CLI\Tests\Context\FeatureContext as WPCLIFeatureContext; use SQLite3; diff --git a/features/sqlite-import.feature b/features/sqlite-import.feature index 060b5b6..ab4975e 100644 --- a/features/sqlite-import.feature +++ b/features/sqlite-import.feature @@ -191,3 +191,24 @@ Feature: WP-CLI SQLite Import Command And the SQLite database should contain a table named "test_table" And the "test_table" should contain a row with name "" + + @require-sqlite + Scenario: Import tables with foreign key constraints when child table is imported before parent + Given a SQL dump file named "test_import.sql" with content: + """ + CREATE TABLE wp_aa_child ( + id INTEGER PRIMARY KEY, + parent_id INTEGER NOT NULL, + CONSTRAINT fk_parent FOREIGN KEY (parent_id) REFERENCES wp_zz_parent(id) + ); + INSERT INTO wp_aa_child (id, parent_id) VALUES (1, 1); + CREATE TABLE wp_zz_parent (id INTEGER PRIMARY KEY, name TEXT NOT NULL); + INSERT INTO wp_zz_parent (id, name) VALUES (1, 'Parent Row'); + """ + When I run `wp sqlite --enable-ast-driver import test_import.sql` + Then STDOUT should contain: + """ + Success: Imported from 'test_import.sql'. + """ + And the SQLite database should contain a table named "wp_zz_parent" + And the SQLite database should contain a table named "wp_aa_child" diff --git a/src/Import.php b/src/Import.php index 892d892..812f301 100644 --- a/src/Import.php +++ b/src/Import.php @@ -49,8 +49,27 @@ public function run( $sql_file_path, $args ) { $this->driver->query( 'SET @BACKUP_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0' ); $this->driver->query( 'SET @BACKUP_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0' ); + /* + * Disable foreign key constraints at the SQLite level during import. + * + * The MySQL SET FOREIGN_KEY_CHECKS=0 above is stored as a session + * variable by the driver but does not translate to SQLite's PRAGMA. + * We need to explicitly disable foreign keys so that tables with + * cross-references can be imported in any order (e.g., alphabetical). + */ + $this->driver->execute_sqlite_query( 'PRAGMA foreign_keys = OFF' ); + $this->execute_statements( $import_file ); + /* + * Re-enable foreign key constraints and verify integrity. + * + * PRAGMA foreign_key_check validates all FK references after the + * full import, catching any actual data integrity issues. + */ + $this->driver->execute_sqlite_query( 'PRAGMA foreign_key_check' ); + $this->driver->execute_sqlite_query( 'PRAGMA foreign_keys = ON' ); + $this->driver->query( 'SET SQL_MODE=@BACKUP_SQL_MODE' ); $this->driver->query( 'SET UNIQUE_CHECKS=@BACKUP_UNIQUE_CHECKS' ); $this->driver->query( 'SET FOREIGN_KEY_CHECKS=@BACKUP_FOREIGN_KEY_CHECKS' );