Skip to content

Commit f06d9aa

Browse files
author
Matt Roberts
committed
Corrects NULL export values.
The code that exports a search-replace command as SQL creates a prepared statement where all columns values are assumed to be strings. Normally this is fine as MySQL/MariaDB will do the conversion work at import. However, in some cases, a column may allow nulls in a numeric field. In this instance, the call to `prepare` will translate a null value into null string. Importing will then fail as null string is not a numeric value. This patch replaces the original code that assumed strings for all bind parameters. Each column value is iterated over and inspected. If the value is not NULL, the value is added to the `$values` array and a bind parameter, `%s` is added to a substituions array. If the value causes `is_null` to return true, only 'NULL' is added to the substituions array. The code then evaluates as it did previously, with a `join` call creating a string from the substitutions array and appending that string to the larger SQL query. This closes #82.
1 parent 5373a84 commit f06d9aa

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

features/search-replace-export.feature

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,17 @@ Feature: Search / replace with file export
359359
"""
360360
'test-remove-placeholder-escape{'
361361
"""
362+
363+
Scenario: NULLs exported as NULL and not null string
364+
Given a WP install
365+
And I run `wp db query "INSERT INTO wp_postmeta VALUES (9999, 9999, NULL, 'foo')"`
366+
367+
When I run `wp search-replace bar replaced wp_postmeta --export`
368+
Then STDOUT should contain:
369+
"""
370+
('9999', '9999', NULL, 'foo')
371+
"""
372+
And STDOUT should not contain:
373+
"""
374+
('9999', '9999', '', 'foo')
375+
"""

src/Search_Replace_Command.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,18 @@ private function write_sql_row_fields( $table, $rows ) {
558558
$export_insert_size = $this->export_insert_size;
559559

560560
foreach($rows as $row_fields) {
561-
$sql .= '(' . join( ', ', array_fill( 0, count( $row_fields ), '%s' ) ) . ')';
562-
$values = array_merge( $values, array_values( $row_fields ) );
561+
$subs = array();
562+
563+
foreach( $row_fields as $field_value ) {
564+
if ( is_null($field_value) ) {
565+
$subs[] = 'NULL';
566+
} else {
567+
$subs[] = '%s';
568+
$values[] = $field_value;
569+
}
570+
}
571+
572+
$sql .= '(' . join( ', ', $subs ) . ')';
563573

564574
// Add new insert statement if needed. Before this we close the previous with semicolon and write statement to sql-file.
565575
// "Statement break" is needed:

0 commit comments

Comments
 (0)