Skip to content

Commit 3033052

Browse files
committed
More fixes & tests
1 parent e2e8e94 commit 3033052

File tree

5 files changed

+157
-14
lines changed

5 files changed

+157
-14
lines changed

features/db-export.feature

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Feature: Export a WordPress database
2020
"""
2121
And the wp_cli_test.sql file should exist
2222

23+
@require-mysql-or-mariadb
2324
Scenario: Exclude tables when exporting the database
2425
Given a WP install
2526

@@ -28,15 +29,57 @@ Feature: Export a WordPress database
2829
And the contents of the wp_cli_test.sql file should not match /CREATE TABLE ["`]?wp_users["`]?/
2930
And the contents of the wp_cli_test.sql file should match /CREATE TABLE ["`]?wp_options["`]?/
3031

32+
@require-mysql-or-mariadb
33+
Scenario: Include only specific tables when exporting the database
34+
Given a WP install
35+
36+
When I try `wp db export wp_cli_test.sql --tables=wp_users --porcelain`
37+
Then the wp_cli_test.sql file should exist
38+
And the contents of the wp_cli_test.sql file should match /CREATE TABLE ["`]?wp_users["`]?/
39+
And the contents of the wp_cli_test.sql file should not match /CREATE TABLE ["`]?wp_posts["`]?/
40+
And the contents of the wp_cli_test.sql file should not match /CREATE TABLE ["`]?wp_options["`]?/
41+
42+
@require-sqlite
43+
Scenario: Exclude tables when exporting the database
44+
Given a WP install
45+
46+
When I try `wp db export wp_cli_test.sql --exclude_tables=wp_users --porcelain`
47+
Then the wp_cli_test.sql file should exist
48+
And the contents of the wp_cli_test.sql file should not match /_mysql_data_types_cache/
49+
And the contents of the wp_cli_test.sql file should not match /CREATE TABLE IF NOT EXISTS ["`]?wp_users["`]?/
50+
And the contents of the wp_cli_test.sql file should match /CREATE TABLE IF NOT EXISTS ["`]?wp_options["`]?/
51+
52+
@require-sqlite
53+
Scenario: Include only specific tables when exporting the database
54+
Given a WP install
55+
56+
When I try `wp db export wp_cli_test.sql --tables=wp_users --porcelain`
57+
Then the wp_cli_test.sql file should exist
58+
And the contents of the wp_cli_test.sql file should not match /_mysql_data_types_cache/
59+
And the contents of the wp_cli_test.sql file should match /CREATE TABLE IF NOT EXISTS ["`]?wp_users["`]?/
60+
And the contents of the wp_cli_test.sql file should not match /CREATE TABLE IF NOT EXISTS ["`]?wp_posts["`]?/
61+
And the contents of the wp_cli_test.sql file should not match /CREATE TABLE IF NOT EXISTS ["`]?wp_options["`]?/
62+
63+
@require-sqlite
3164
Scenario: Export database to STDOUT
3265
Given a WP install
3366

3467
When I run `wp db export -`
3568
Then STDOUT should contain:
3669
"""
37-
-- Dump completed on
70+
PRAGMA foreign_keys=OFF
3871
"""
3972

73+
@require-mysql-or-mariadb
74+
Scenario: Export database to STDOUT
75+
Given a WP install
76+
77+
When I run `wp db export -`
78+
Then STDOUT should contain:
79+
"""
80+
-- Dump completed on
81+
"""
82+
@require-mysql-or-mariadb
4083
Scenario: Export database with mysql defaults to STDOUT
4184
Given a WP install
4285

@@ -46,6 +89,7 @@ Feature: Export a WordPress database
4689
-- Dump completed on
4790
"""
4891

92+
@require-mysql-or-mariadb
4993
Scenario: Export database with mysql --no-defaults to STDOUT
5094
Given a WP install
5195

features/db-search.feature

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -924,12 +924,64 @@ Feature: Search through the database
924924
"""
925925
Success: Found
926926
"""
927-
And STDOUT should contain:
927+
And STDOUT should match /\d tables? skipped:.*wp_term_relationships/
928+
And STDERR should be empty
929+
930+
Scenario: Search with output options
931+
Given a WP install
932+
933+
When I run `wp db query "SELECT option_id FROM wp_options WHERE option_name = 'siteurl';" --skip-column-names | cat`
934+
Then save STDOUT as {SITEURL_ID}
935+
936+
When I run `wp db query "SELECT option_id FROM wp_options WHERE option_name = 'home';" --skip-column-names | cat`
937+
Then save STDOUT as {HOMEURL_ID}
938+
939+
When I run `wp db search example.com`
940+
Then STDOUT should contain:
941+
"""
942+
wp_options:option_value
943+
{SITEURL_ID}:https://example.com
944+
wp_options:option_value
945+
{HOMEURL_ID}:https://example.com
946+
"""
947+
948+
When I run `wp db search example.com --table_column_once`
949+
Then STDOUT should contain:
950+
"""
951+
wp_options:option_value
952+
{SITEURL_ID}:https://example.com
953+
{HOMEURL_ID}:https://example.com
928954
"""
929-
1 table skipped: wp_term_relationships.
955+
956+
When I run `wp db search example.com --one_line`
957+
Then STDOUT should contain:
958+
"""
959+
wp_options:option_value:{SITEURL_ID}:https://example.com
960+
wp_options:option_value:{HOMEURL_ID}:https://example.com
961+
"""
962+
963+
When I run `wp db search example.com --table_column_once --one_line`
964+
Then STDOUT should contain:
965+
"""
966+
wp_options:option_value:{SITEURL_ID}:https://example.com
967+
wp_options:option_value:{HOMEURL_ID}:https://example.com
968+
"""
969+
970+
When I run `wp db search example.com --all-tables --before_context=0 --after_context=0 --matches_only`
971+
Then STDOUT should not contain:
972+
"""
973+
:
930974
"""
931975
And STDERR should be empty
932976

977+
When I run `wp db search example.com --all-tables --before_context=0 --after_context=0 --stats`
978+
Then STDOUT should contain:
979+
"""
980+
Success: Found
981+
"""
982+
And STDOUT should match /\d tables? skipped:.*wp_term_relationships/
983+
And STDERR should be empty
984+
933985
Scenario: Search with custom colors
934986
Given a WP install
935987

@@ -993,6 +1045,9 @@ Feature: Search through the database
9931045
"""
9941046
And the return code should be 0
9951047

1048+
# SQLite doesn't support SOURCE statement.
1049+
# TODO: Add similar test for SQLite.
1050+
@require-mysql-or-mariadb
9961051
Scenario: Search should cater for field/table names that use reserved words or unusual characters
9971052
Given a WP install
9981053
And a esc_sql_ident.sql file:

features/db-tables.feature

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,14 @@ Feature: List database tables
341341
"""
342342

343343
When I run `wp db tables '*_posts' --scope=blog --network`
344-
Then STDOUT should be:
344+
Then STDOUT should contain:
345345
"""
346-
as_wp_2_posts
347346
as_wp_posts
348347
"""
348+
And STDOUT should contain:
349+
"""
350+
as_wp_2_posts
351+
"""
349352

350353
When I try `wp db tables '*_posts' --scope=global`
351354
Then STDERR should not be empty

src/DB_Command.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -906,7 +906,7 @@ public function import( $args, $assoc_args ) {
906906
}
907907

908908
if ( $this->is_sqlite() ) {
909-
$this->sqlite_import( $result_file );
909+
$this->sqlite_import( $result_file, $assoc_args );
910910
return;
911911
}
912912

src/DB_Command_SQLite.php

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)