From 970cf3f958a5d42cb4eb75ae63bbbf0671efa0ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Feb 2026 16:05:09 +0000 Subject: [PATCH 1/7] Initial plan From 0a6e26545b9900fe80b5915df0f2ac9619894a78 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Feb 2026 16:10:08 +0000 Subject: [PATCH 2/7] Add wp db status command implementation Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- composer.json | 3 +- features/db-status.feature | 56 ++++++++++++++++++++++ src/DB_Command.php | 95 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 features/db-status.feature diff --git a/composer.json b/composer.json index e575f01f..34fbdb20 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,8 @@ "db search", "db tables", "db size", - "db columns" + "db columns", + "db status" ] }, "autoload": { diff --git a/features/db-status.feature b/features/db-status.feature new file mode 100644 index 00000000..b758e4e1 --- /dev/null +++ b/features/db-status.feature @@ -0,0 +1,56 @@ +Feature: Display database status overview + + Scenario: Display database status for a WordPress install + Given a WP install + + When I run `wp db status` + Then STDOUT should contain: + """ + Database Name: + """ + And STDOUT should contain: + """ + Tables: + """ + And STDOUT should contain: + """ + Total Size: + """ + And STDOUT should contain: + """ + Prefix: wp_ + """ + And STDOUT should contain: + """ + Engine: + """ + And STDOUT should contain: + """ + Charset: + """ + And STDOUT should contain: + """ + Collation: + """ + And STDOUT should contain: + """ + Check Status: + """ + + Scenario: Verify database status shows correct database name + Given a WP install + + When I run `wp db status` + Then STDOUT should contain: + """ + wp_cli_test + """ + + Scenario: Verify database status shows check status as OK + Given a WP install + + When I run `wp db status` + Then STDOUT should contain: + """ + Check Status: OK + """ diff --git a/src/DB_Command.php b/src/DB_Command.php index 77676172..da8b0d90 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -1247,6 +1247,101 @@ public function prefix() { WP_CLI::log( $wpdb->prefix ); } + /** + * Displays a quick database status overview. + * + * Shows key database information including name, table count, size, + * prefix, engine, charset, collation, and health check status. This + * command is useful for getting a quick snapshot of database health + * without needing to run multiple separate commands. + * + * ## EXAMPLES + * + * $ wp db status + * Database Name: wp_cli_test + * Tables: 54 + * Total Size: 312 KB + * Prefix: wp_ + * Engine: InnoDB + * Charset: utf8mb4 + * Collation: utf8mb4_unicode_ci + * Check Status: OK + * + * @when after_wp_load + */ + public function status() { + global $wpdb; + + // Get database name. + $db_name = DB_NAME; + + // Get table count. + $table_count = count( Utils\wp_get_table_names( [], [ 'scope' => 'all' ] ) ); + + // Get total database size. + $db_size_bytes = $wpdb->get_var( + $wpdb->prepare( + 'SELECT SUM(data_length + index_length) FROM information_schema.TABLES where table_schema = %s GROUP BY table_schema;', + DB_NAME + ) + ); + + // Format size to human-readable. + $size_key = floor( log( (float) $db_size_bytes ) / log( 1000 ) ); + $sizes = [ 'B', 'KB', 'MB', 'GB', 'TB' ]; + $size_format = isset( $sizes[ $size_key ] ) ? $sizes[ $size_key ] : $sizes[0]; + $divisor = pow( 1000, $size_key ); + $db_size = round( (int) $db_size_bytes / $divisor, 2 ) . ' ' . $size_format; + + // Get prefix. + $prefix = $wpdb->prefix; + + // Get engine, charset, and collation from information_schema (using a common table). + $table_info = $wpdb->get_row( + $wpdb->prepare( + 'SELECT ENGINE as engine, CCSA.character_set_name as charset, TABLE_COLLATION as collation ' + . 'FROM information_schema.TABLES T ' + . 'LEFT JOIN information_schema.COLLATION_CHARACTER_SET_APPLICABILITY CCSA ' + . 'ON CCSA.collation_name = T.table_collation ' + . 'WHERE T.table_schema = %s ' + . 'AND T.table_name LIKE %s ' + . 'LIMIT 1', + DB_NAME, + $wpdb->esc_like( $prefix ) . '%' + ) + ); + + $engine = $table_info && isset( $table_info->engine ) ? $table_info->engine : 'N/A'; + $charset = $table_info && isset( $table_info->charset ) ? $table_info->charset : 'N/A'; + $collation = $table_info && isset( $table_info->collation ) ? $table_info->collation : 'N/A'; + + // Run database check silently to get status. + $check_args = []; + $command = sprintf( + '/usr/bin/env %s%s %s', + Utils\get_sql_check_command(), + $this->get_defaults_flag_string( $check_args ), + '%s' + ); + list( $stdout, $stderr, $exit_code ) = self::run( + Utils\esc_cmd( $command, DB_NAME ), + [ 'check' => true ], + false + ); + + $check_status = ( 0 === $exit_code ) ? 'OK' : 'Error'; + + // Output formatted status. + WP_CLI::log( sprintf( '%-18s %s', 'Database Name:', $db_name ) ); + WP_CLI::log( sprintf( '%-18s %d', 'Tables:', $table_count ) ); + WP_CLI::log( sprintf( '%-18s %s', 'Total Size:', $db_size ) ); + WP_CLI::log( sprintf( '%-18s %s', 'Prefix:', $prefix ) ); + WP_CLI::log( sprintf( '%-18s %s', 'Engine:', $engine ) ); + WP_CLI::log( sprintf( '%-18s %s', 'Charset:', $charset ) ); + WP_CLI::log( sprintf( '%-18s %s', 'Collation:', $collation ) ); + WP_CLI::log( sprintf( '%-18s %s', 'Check Status:', $check_status ) ); + } + /** * Finds a string in the database. * From 7c06ca33ae7cba7bb2ad5b85b9e254c096433a39 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Feb 2026 16:11:23 +0000 Subject: [PATCH 3/7] Fix edge case handling for zero database size Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/DB_Command.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/DB_Command.php b/src/DB_Command.php index da8b0d90..dc2d5ac9 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -1287,11 +1287,15 @@ public function status() { ); // Format size to human-readable. - $size_key = floor( log( (float) $db_size_bytes ) / log( 1000 ) ); - $sizes = [ 'B', 'KB', 'MB', 'GB', 'TB' ]; - $size_format = isset( $sizes[ $size_key ] ) ? $sizes[ $size_key ] : $sizes[0]; - $divisor = pow( 1000, $size_key ); - $db_size = round( (int) $db_size_bytes / $divisor, 2 ) . ' ' . $size_format; + if ( empty( $db_size_bytes ) || $db_size_bytes <= 0 ) { + $db_size = '0 B'; + } else { + $size_key = floor( log( (float) $db_size_bytes ) / log( 1000 ) ); + $sizes = [ 'B', 'KB', 'MB', 'GB', 'TB' ]; + $size_format = isset( $sizes[ $size_key ] ) ? $sizes[ $size_key ] : $sizes[0]; + $divisor = pow( 1000, $size_key ); + $db_size = round( (int) $db_size_bytes / $divisor, 2 ) . ' ' . $size_format; + } // Get prefix. $prefix = $wpdb->prefix; From 94d0fea06600b4686908dbf61636a52361303304 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 2 Feb 2026 20:47:50 -0500 Subject: [PATCH 4/7] Update src/DB_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/DB_Command.php | 48 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/src/DB_Command.php b/src/DB_Command.php index dc2d5ac9..32c83df4 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -1300,25 +1300,59 @@ public function status() { // Get prefix. $prefix = $wpdb->prefix; - // Get engine, charset, and collation from information_schema (using a common table). + // Get engine, charset, and collation from information_schema across all tables with the prefix. $table_info = $wpdb->get_row( $wpdb->prepare( - 'SELECT ENGINE as engine, CCSA.character_set_name as charset, TABLE_COLLATION as collation ' + 'SELECT ' + . 'COUNT(DISTINCT ENGINE) AS engine_count, ' + . 'MIN(ENGINE) AS engine, ' + . 'COUNT(DISTINCT CCSA.character_set_name) AS charset_count, ' + . 'MIN(CCSA.character_set_name) AS charset, ' + . 'COUNT(DISTINCT TABLE_COLLATION) AS collation_count, ' + . 'MIN(TABLE_COLLATION) AS collation ' . 'FROM information_schema.TABLES T ' . 'LEFT JOIN information_schema.COLLATION_CHARACTER_SET_APPLICABILITY CCSA ' . 'ON CCSA.collation_name = T.table_collation ' . 'WHERE T.table_schema = %s ' - . 'AND T.table_name LIKE %s ' - . 'LIMIT 1', + . 'AND T.table_name LIKE %s', DB_NAME, $wpdb->esc_like( $prefix ) . '%' ) ); - $engine = $table_info && isset( $table_info->engine ) ? $table_info->engine : 'N/A'; - $charset = $table_info && isset( $table_info->charset ) ? $table_info->charset : 'N/A'; - $collation = $table_info && isset( $table_info->collation ) ? $table_info->collation : 'N/A'; + if ( $table_info ) { + $engine_count = isset( $table_info->engine_count ) ? (int) $table_info->engine_count : 0; + $charset_count = isset( $table_info->charset_count ) ? (int) $table_info->charset_count : 0; + $collation_count = isset( $table_info->collation_count ) ? (int) $table_info->collation_count : 0; + if ( $engine_count > 1 ) { + $engine = 'Mixed'; + } elseif ( isset( $table_info->engine ) && '' !== $table_info->engine ) { + $engine = $table_info->engine; + } else { + $engine = 'N/A'; + } + + if ( $charset_count > 1 ) { + $charset = 'Mixed'; + } elseif ( isset( $table_info->charset ) && '' !== $table_info->charset ) { + $charset = $table_info->charset; + } else { + $charset = 'N/A'; + } + + if ( $collation_count > 1 ) { + $collation = 'Mixed'; + } elseif ( isset( $table_info->collation ) && '' !== $table_info->collation ) { + $collation = $table_info->collation; + } else { + $collation = 'N/A'; + } + } else { + $engine = 'N/A'; + $charset = 'N/A'; + $collation = 'N/A'; + } // Run database check silently to get status. $check_args = []; $command = sprintf( From ba356779b4c43f67ee5c15cc0e5c6fa0f7368fdd Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 2 Feb 2026 20:47:59 -0500 Subject: [PATCH 5/7] Update src/DB_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/DB_Command.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DB_Command.php b/src/DB_Command.php index 32c83df4..60f8286b 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -1290,11 +1290,11 @@ public function status() { if ( empty( $db_size_bytes ) || $db_size_bytes <= 0 ) { $db_size = '0 B'; } else { - $size_key = floor( log( (float) $db_size_bytes ) / log( 1000 ) ); + $size_key = floor( log( $db_size_bytes ) / log( 1000 ) ); $sizes = [ 'B', 'KB', 'MB', 'GB', 'TB' ]; $size_format = isset( $sizes[ $size_key ] ) ? $sizes[ $size_key ] : $sizes[0]; $divisor = pow( 1000, $size_key ); - $db_size = round( (int) $db_size_bytes / $divisor, 2 ) . ' ' . $size_format; + $db_size = round( $db_size_bytes / $divisor, 2 ) . ' ' . $size_format; } // Get prefix. From 66478f60014b67445129200f1bfc0321662ed911 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 2 Feb 2026 20:48:19 -0500 Subject: [PATCH 6/7] Update src/DB_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/DB_Command.php | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/DB_Command.php b/src/DB_Command.php index 60f8286b..7d89b79a 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -1354,21 +1354,24 @@ public function status() { $collation = 'N/A'; } // Run database check silently to get status. - $check_args = []; - $command = sprintf( - '/usr/bin/env %s%s %s', - Utils\get_sql_check_command(), - $this->get_defaults_flag_string( $check_args ), - '%s' - ); - list( $stdout, $stderr, $exit_code ) = self::run( - Utils\esc_cmd( $command, DB_NAME ), - [ 'check' => true ], - false - ); - - $check_status = ( 0 === $exit_code ) ? 'OK' : 'Error'; - + if ( $table_count > 0 ) { + $check_args = []; + $command = sprintf( + '/usr/bin/env %s%s %s', + Utils\get_sql_check_command(), + $this->get_defaults_flag_string( $check_args ), + '%s' + ); + list( $stdout, $stderr, $exit_code ) = self::run( + Utils\esc_cmd( $command, DB_NAME ), + [ 'check' => true ], + false + ); + $check_status = ( 0 === $exit_code ) ? 'OK' : 'Error'; + } else { + // No tables to check; mark status as not applicable. + $check_status = 'N/A'; + } // Output formatted status. WP_CLI::log( sprintf( '%-18s %s', 'Database Name:', $db_name ) ); WP_CLI::log( sprintf( '%-18s %d', 'Tables:', $table_count ) ); From 8a0d032499e026430a5636b3557a39bd760866b7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Feb 2026 02:04:24 +0000 Subject: [PATCH 7/7] Fix wp db status to accept parameters and run before WordPress loads Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/db-status.feature | 66 ++++++++++++++++++++++++++++++++++++++ src/DB_Command.php | 20 +++++++++--- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/features/db-status.feature b/features/db-status.feature index b758e4e1..1702184f 100644 --- a/features/db-status.feature +++ b/features/db-status.feature @@ -54,3 +54,69 @@ Feature: Display database status overview """ Check Status: OK """ + + Scenario: Run db status with MySQL defaults to check the database + Given a WP install + + When I run `wp db status --defaults` + Then STDOUT should contain: + """ + Database Name: + """ + And STDOUT should contain: + """ + Check Status: OK + """ + + Scenario: Run db status with --no-defaults to check the database + Given a WP install + + When I run `wp db status --no-defaults` + Then STDOUT should contain: + """ + Database Name: + """ + And STDOUT should contain: + """ + Check Status: OK + """ + + Scenario: Run db status with passed-in options + Given a WP install + + When I run `wp db status --dbuser=wp_cli_test` + Then STDOUT should contain: + """ + Database Name: + """ + And STDOUT should contain: + """ + Check Status: OK + """ + + When I run `wp db status --dbpass=password1` + Then STDOUT should contain: + """ + Database Name: + """ + And STDOUT should contain: + """ + Check Status: OK + """ + + When I run `wp db status --dbuser=wp_cli_test --dbpass=password1` + Then STDOUT should contain: + """ + Database Name: + """ + And STDOUT should contain: + """ + Check Status: OK + """ + + When I try `wp db status --dbuser=no_such_user` + Then the return code should not be 0 + + When I try `wp db status --dbpass=no_such_pass` + Then the return code should not be 0 + diff --git a/src/DB_Command.php b/src/DB_Command.php index 7d89b79a..a66800b0 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -1255,6 +1255,17 @@ public function prefix() { * command is useful for getting a quick snapshot of database health * without needing to run multiple separate commands. * + * ## OPTIONS + * + * [--dbuser=] + * : Username to pass to mysql. Defaults to DB_USER. + * + * [--dbpass=] + * : Password to pass to mysql. Defaults to DB_PASSWORD. + * + * [--defaults] + * : Loads the environment's MySQL option files. Default behavior is to skip loading them to avoid failures due to misconfiguration. + * * ## EXAMPLES * * $ wp db status @@ -1267,9 +1278,9 @@ public function prefix() { * Collation: utf8mb4_unicode_ci * Check Status: OK * - * @when after_wp_load + * @when before_wp_load */ - public function status() { + public function status( $_, $assoc_args ) { global $wpdb; // Get database name. @@ -1355,16 +1366,15 @@ public function status() { } // Run database check silently to get status. if ( $table_count > 0 ) { - $check_args = []; $command = sprintf( '/usr/bin/env %s%s %s', Utils\get_sql_check_command(), - $this->get_defaults_flag_string( $check_args ), + $this->get_defaults_flag_string( $assoc_args ), '%s' ); list( $stdout, $stderr, $exit_code ) = self::run( Utils\esc_cmd( $command, DB_NAME ), - [ 'check' => true ], + array_merge( [ 'check' => true ], $assoc_args ), false ); $check_status = ( 0 === $exit_code ) ? 'OK' : 'Error';