Skip to content

Commit 940b2d4

Browse files
CopilotswissspidyCopilot
authored
Alert user of database table permission errors during search-replace (#216)
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Pascal Birchler <pascalb@google.com>
1 parent 69f1ed3 commit 940b2d4

2 files changed

Lines changed: 54 additions & 3 deletions

File tree

features/search-replace.feature

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,3 +1598,21 @@ Feature: Do global search/replace
15981598
"""
15991599
--old-content
16001600
"""
1601+
1602+
1603+
@require-mysql
1604+
Scenario: Warn when updating a table fails due to a database error
1605+
Given a WP install
1606+
And I run `wp db query "CREATE TABLE wp_readonly_test ( id int(11) unsigned NOT NULL AUTO_INCREMENT, data TEXT, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"`
1607+
And I run `wp db query "INSERT INTO wp_readonly_test (data) VALUES ('old-value');"`
1608+
And I run `wp db query "CREATE TRIGGER prevent_update BEFORE UPDATE ON wp_readonly_test FOR EACH ROW SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Table is read-only';"`
1609+
1610+
When I try `wp search-replace old-value new-value --all-tables-with-prefix`
1611+
Then STDERR should contain:
1612+
"""
1613+
Error updating column 'data' in table 'wp_readonly_test'
1614+
"""
1615+
And STDERR should contain:
1616+
"""
1617+
Table is read-only
1618+
"""

src/Search_Replace_Command.php

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ class Search_Replace_Command extends WP_CLI_Command {
1919
*/
2020
private $export_handle = false;
2121

22+
/**
23+
* Tracks table/column combinations that have encountered update errors,
24+
* so we can avoid repeated failing updates and noisy per-row warnings.
25+
*
26+
* @var array
27+
*/
28+
private $update_error_columns = array();
29+
2230
/**
2331
* @var int
2432
*/
@@ -697,6 +705,9 @@ private function sql_handle_col( $col, $primary_keys, $table, $old, $new ) {
697705
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
698706
$count = (int) $wpdb->query( $wpdb->prepare( "UPDATE $table_sql SET $col_sql = REPLACE($col_sql, %s, %s);", $old, $new ) );
699707
}
708+
if ( $wpdb->last_error ) {
709+
WP_CLI::warning( sprintf( "Error updating column '%s' in table '%s': %s", $col, $table, $wpdb->last_error ) );
710+
}
700711
}
701712

702713
if ( $this->verbose && 'table' === $this->format ) {
@@ -775,14 +786,36 @@ static function ( $key ) {
775786
$replacer->clear_log_data();
776787
}
777788

778-
++$count;
779-
if ( ! $this->dry_run ) {
789+
// If we've already seen an update error for this table/column and are not in dry-run,
790+
// skip further attempts to avoid repeated failures and noisy warnings.
791+
if ( ! $this->dry_run && ! empty( $this->update_error_columns[ $table ][ $col ] ) ) {
792+
continue;
793+
}
794+
795+
if ( $this->dry_run ) {
796+
// In dry-run mode, count replacements once a change has been detected.
797+
++$count;
798+
} else {
780799
$update_where = array();
781800
foreach ( (array) $keys as $k => $v ) {
782801
$update_where[ $k ] = $v;
783802
}
784803

785-
$wpdb->update( $table, [ $col => $value ], $update_where );
804+
$result = $wpdb->update( $table, array( $col => $value ), $update_where );
805+
if ( false === $result ) {
806+
if ( empty( $this->update_error_columns[ $table ][ $col ] ) ) {
807+
$this->update_error_columns[ $table ][ $col ] = true;
808+
if ( $wpdb->last_error ) {
809+
WP_CLI::warning( sprintf( "Error updating column '%s' in table '%s': %s", $col, $table, $wpdb->last_error ) );
810+
} else {
811+
WP_CLI::warning( sprintf( "Error updating column '%s' in table '%s'.", $col, $table ) );
812+
}
813+
}
814+
continue;
815+
}
816+
817+
// Only count successful updates.
818+
++$count;
786819
}
787820
}
788821

0 commit comments

Comments
 (0)