Skip to content

Commit

Permalink
Enable --format=<format> for db search (#247)
Browse files Browse the repository at this point in the history
* Enable formatter for search command

* Use `value` instead of `ID` for the primary key column

* Rename and reorder the columns

* Update docs

* Less brittle test

---------

Co-authored-by: Daniel Bachhuber <daniel.bachhuber@automattic.com>
  • Loading branch information
2ndkauboy and danielbachhuber authored Apr 27, 2024
1 parent 41b502b commit bf741eb
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 3 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ defined in the SQL.
Finds a string in the database.

~~~
wp db search <search> [<tables>...] [--network] [--all-tables-with-prefix] [--all-tables] [--before_context=<num>] [--after_context=<num>] [--regex] [--regex-flags=<regex-flags>] [--regex-delimiter=<regex-delimiter>] [--table_column_once] [--one_line] [--matches_only] [--stats] [--table_column_color=<color_code>] [--id_color=<color_code>] [--match_color=<color_code>]
wp db search <search> [<tables>...] [--network] [--all-tables-with-prefix] [--all-tables] [--before_context=<num>] [--after_context=<num>] [--regex] [--regex-flags=<regex-flags>] [--regex-delimiter=<regex-delimiter>] [--table_column_once] [--one_line] [--matches_only] [--stats] [--table_column_color=<color_code>] [--id_color=<color_code>] [--match_color=<color_code>] [--fields=<fields>] [--format=<format>]
~~~

Searches through all of the text columns in a selection of database tables for a given string, Outputs colorized references to the string.
Expand Down Expand Up @@ -626,6 +626,12 @@ Defaults to searching through all tables registered to $wpdb. On multisite, this
[--match_color=<color_code>]
Percent color code to use for the match (unless both before and after context are 0, when no color code is used). For a list of available percent color codes, see below. Default '%3%k' (black on a mustard background).

[--fields=<fields>]
Get a specific subset of the fields.

[--format=<format>]
Render output in a particular format.

The percent color codes available are:

| Code | Color
Expand Down Expand Up @@ -694,6 +700,21 @@ They can be concatenated. For instance, the default match color of black on a mu
# SQL search and delete records from database table 'wp_options' where 'option_name' match 'foo'
wp db query "DELETE from wp_options where option_id in ($(wp db query "SELECT GROUP_CONCAT(option_id SEPARATOR ',') from wp_options where option_name like '%foo%';" --silent --skip-column-names))"

# Search for a string and print the result as a table
$ wp db search https://localhost:8889 --format=table --fields=table,column,match
+------------+--------------+-----------------------------+
| table | column | match |
+------------+--------------+-----------------------------+
| wp_options | option_value | https://localhost:8889 |
| wp_options | option_value | https://localhost:8889 |
| wp_posts | guid | https://localhost:8889/?p=1 |
| wp_users | user_url | https://localhost:8889 |
+------------+--------------+-----------------------------+

# Search for a string and get only the IDs (only works for a single table)
$ wp db search https://localhost:8889 wp_options --format=ids
1 2



### wp db tables
Expand Down
20 changes: 20 additions & 0 deletions features/db-search.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1066,3 +1066,23 @@ Feature: Search through the database
:aöXYXYX
"""
And STDERR should be empty

Scenario: Search for a string and output the format as a table
Given a WP install

When I run `wp db search mail.example.com --format=csv`
Then STDOUT should contain:
"""
wp_options,option_value,mail.example.com,option_id
"""

When I try `wp db search example.com --format=ids`
Then STDERR should be:
"""
Error: The "ids" format can only be used for a single table.
"""
And STDOUT should be empty
And the return code should be 1

When I run `wp db search mail.example.com wp_options --format=ids`
Then STDOUT should not be empty
66 changes: 64 additions & 2 deletions src/DB_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,12 @@ public function prefix() {
* [--match_color=<color_code>]
* : Percent color code to use for the match (unless both before and after context are 0, when no color code is used). For a list of available percent color codes, see below. Default '%3%k' (black on a mustard background).
*
* [--fields=<fields>]
* : Get a specific subset of the fields.
*
* [--format=<format>]
* : Render output in a particular format.
*
* The percent color codes available are:
*
* | Code | Color
Expand Down Expand Up @@ -1326,6 +1332,21 @@ public function prefix() {
* # SQL search and delete records from database table 'wp_options' where 'option_name' match 'foo'
* wp db query "DELETE from wp_options where option_id in ($(wp db query "SELECT GROUP_CONCAT(option_id SEPARATOR ',') from wp_options where option_name like '%foo%';" --silent --skip-column-names))"
*
* # Search for a string and print the result as a table
* $ wp db search https://localhost:8889 --format=table --fields=table,column,match
* +------------+--------------+-----------------------------+
* | table | column | match |
* +------------+--------------+-----------------------------+
* | wp_options | option_value | https://localhost:8889 |
* | wp_options | option_value | https://localhost:8889 |
* | wp_posts | guid | https://localhost:8889/?p=1 |
* | wp_users | user_url | https://localhost:8889 |
* +------------+--------------+-----------------------------+
*
* # Search for a string and get only the IDs (only works for a single table)
* $ wp db search https://localhost:8889 wp_options --format=ids
* 1 2
*
* @when after_wp_load
*/
public function search( $args, $assoc_args ) {
Expand Down Expand Up @@ -1365,6 +1386,8 @@ public function search( $args, $assoc_args ) {
$one_line = Utils\get_flag_value( $assoc_args, 'one_line', false );
$matches_only = Utils\get_flag_value( $assoc_args, 'matches_only', false );
$stats = Utils\get_flag_value( $assoc_args, 'stats', false );
$fields = Utils\get_flag_value( $assoc_args, 'fields' );
$format = Utils\get_flag_value( $assoc_args, 'format' );

$column_count = 0;
$row_count = 0;
Expand Down Expand Up @@ -1399,6 +1422,8 @@ public function search( $args, $assoc_args ) {

$tables = Utils\wp_get_table_names( $args, $assoc_args );

$search_results = [];

$start_search_time = microtime( true );

foreach ( $tables as $table ) {
Expand Down Expand Up @@ -1442,7 +1467,7 @@ public function search( $args, $assoc_args ) {
foreach ( $results as $result ) {
$col_val = $result->$column;
if ( preg_match_all( $search_regex, $col_val, $matches, PREG_OFFSET_CAPTURE ) ) {
if ( ! $matches_only && ( ! $table_column_once || ! $outputted_table_column_once ) && ! $one_line ) {
if ( ! $format && ! $matches_only && ( ! $table_column_once || ! $outputted_table_column_once ) && ! $one_line ) {
WP_CLI::log( $table_column_val );
$outputted_table_column_once = true;
}
Expand Down Expand Up @@ -1490,13 +1515,50 @@ public function search( $args, $assoc_args ) {
$match_count += $match_cnt;
$col_val = implode( ' [...] ', $bits );

WP_CLI::log( $matches_only ? $col_val : ( $one_line ? "{$table_column_val}:{$pk_val}{$col_val}" : "{$pk_val}{$col_val}" ) );
if ( $format ) {
$search_results[] = [
'table' => $table,
'column' => $column,
// Remove the colors for the format output.
'match' => str_replace(
[ $colors['match'][0], $colors['match'][1] ],
[ '','' ],
$col_val
),
'primary_key_name' => $primary_key,
'primary_key_value' => $result->$primary_key,
];
} else {
WP_CLI::log( $matches_only ? $col_val : ( $one_line ? "{$table_column_val}:{$pk_val}{$col_val}" : "{$pk_val}{$col_val}" ) );
}
}
}
}
}
}

if ( $format ) {
$formatter_args = [
'format' => $format,
];
$formatter_fields = [ 'table', 'column', 'match', 'primary_key_name', 'primary_key_value' ];

if ( $fields ) {
$fields = explode( ',', $assoc_args['fields'] );
$formatter_fields = array_values( array_intersect( $formatter_fields, $fields ) );
}

if ( in_array( $format, [ 'ids', 'count' ], true ) ) {
if ( count( $tables ) > 1 ) {
WP_CLI::error( 'The "ids" format can only be used for a single table.' );
}
$search_results = array_column( $search_results, 'primary_key_value' );
}

$formatter = new Formatter( $formatter_args, $formatter_fields );
$formatter->display_items( $search_results );
}

if ( $stats ) {
$table_count = count( $tables );
$skipped_count = count( $skipped );
Expand Down

0 comments on commit bf741eb

Please sign in to comment.