@@ -267,19 +267,48 @@ protected function sqlite_export( $file, $assoc_args ) {
267267
268268 copy ( $ db_path , $ temp_db );
269269
270- $ drop_tables = '' ;
271-
272270 $ exclude_tables = [];
271+
272+ // When passing --tables, exclude everything *except* the tables requested.
273+ if ( isset ( $ assoc_args ['tables ' ] ) ) {
274+ $ include_tables = explode ( ', ' , trim ( $ assoc_args ['tables ' ], ', ' ) );
275+ unset( $ assoc_args ['tables ' ] );
276+
277+ // Use the sqlite3 binary to fetch all table names
278+ $ query = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'; " ;
279+
280+ // Build the command safely
281+ $ command = 'sqlite3 ' . escapeshellarg ( $ temp_db ) . ' ' . escapeshellarg ( $ query );
282+
283+ WP_CLI ::debug ( "Running shell command: {$ command }" , 'db ' );
284+
285+ $ result = \WP_CLI \Process::create ( $ command , null , null )->run ();
286+
287+ if ( 0 !== $ result ->return_code ) {
288+ WP_CLI ::error ( 'Could not export database ' );
289+ }
290+
291+ $ all_tables = explode ( "\n" , $ result ->stdout );
292+
293+ $ exclude_tables = array_diff ( $ all_tables , $ include_tables );
294+ }
295+
273296 if ( isset ( $ assoc_args ['exclude_tables ' ] ) ) {
274297 $ exclude_tables = explode ( ', ' , trim ( $ assoc_args ['exclude_tables ' ], ', ' ) );
275298 unset( $ assoc_args ['exclude_tables ' ] );
276299 }
300+
301+ // Always exclude this one created by the drop-in.
277302 $ exclude_tables [] = '_mysql_data_types_cache ' ;
303+
304+ $ exclude_tables = array_unique ( array_filter ( $ exclude_tables ) );
305+
306+ $ command = "sqlite3 $ temp_db " ;
278307 foreach ( $ exclude_tables as $ table ) {
279- $ drop_tables .= sprintf ( '"DROP TABLE %s;" ' , $ table );
308+ $ command .= sprintf ( '"DROP TABLE %s;" ' , $ table );
280309 }
281310
282- $ command = " sqlite3 $ temp_db $ drop_tables " ;
311+ $ command = trim ( $ command ) ;
283312
284313 WP_CLI ::debug ( "Running shell command: {$ command }" , 'db ' );
285314
@@ -321,9 +350,10 @@ protected function sqlite_export( $file, $assoc_args ) {
321350 /**
322351 * Import SQL into SQLite database.
323352 *
324- * @param string $file Input file path.
353+ * @param string $file Input file path.
354+ * @param array $assoc_args Associative arguments.
325355 */
326- protected function sqlite_import ( $ file ) {
356+ protected function sqlite_import ( $ file, $ assoc_args ) {
327357 $ db_path = $ this ->get_sqlite_db_path ();
328358
329359 if ( ! $ db_path ) {
@@ -343,20 +373,31 @@ protected function sqlite_import( $file ) {
343373 }
344374
345375 $ import_file = tempnam ( sys_get_temp_dir (), 'temp.db ' );
376+
377+ if ( false === $ import_file ) {
378+ WP_CLI ::error ( 'Failed to read from stdin. ' );
379+ }
380+
346381 file_put_contents ( $ import_file , $ sql );
347382 $ file = 'STDIN ' ;
348383 } elseif ( ! is_readable ( $ file ) ) {
349384 WP_CLI ::error ( sprintf ( 'Import file missing or not readable: %s ' , $ file ) );
350385 }
351386
352387 // Ignore errors about unique constraints and existing indexes.
353- $ contents = file_get_contents ( $ import_file );
388+ $ contents = ( string ) file_get_contents ( $ import_file );
354389 $ contents = str_replace ( 'INSERT INTO ' , 'INSERT OR IGNORE INTO ' , $ contents );
355390 $ contents = str_replace ( 'CREATE INDEX " ' , 'CREATE INDEX IF NOT EXISTS " ' , $ contents );
356391 $ contents = str_replace ( 'CREATE UNIQUE INDEX " ' , 'CREATE UNIQUE INDEX IF NOT EXISTS " ' , $ contents );
357392 file_put_contents ( $ import_file , $ contents );
358393
359- $ command = "sqlite3 $ db_path < $ import_file " ;
394+ $ command = 'sqlite3 ' ;
395+
396+ if ( ! Utils \get_flag_value ( $ assoc_args , 'skip-optimization ' ) ) {
397+ $ command .= '-cmd "PRAGMA foreign_keys=OFF;" -cmd "PRAGMA ignore_check_constraints=ON;" -cmd "PRAGMA synchronous=OFF;" -cmd "PRAGMA journal_mode=MEMORY;" ' ;
398+ }
399+
400+ $ command .= "$ db_path < $ import_file " ;
360401
361402 WP_CLI ::debug ( "Running shell command: {$ command }" , 'db ' );
362403
0 commit comments