diff --git a/includes/migration/class-tmdo-native-restorer.php b/includes/migration/class-tmdo-native-restorer.php index 4bd8c1d..cf97d42 100644 --- a/includes/migration/class-tmdo-native-restorer.php +++ b/includes/migration/class-tmdo-native-restorer.php @@ -168,8 +168,9 @@ final class TMDO_Native_Restorer { if ( '' === $col || ! isset( $row[ $col ] ) ) { continue; } - $want = (string) maybe_serialize( TMDO_Type_Caster::from_db( $row[ $col ], $field ) ); - $native = $wpdb->get_col( $wpdb->prepare( "SELECT meta_value FROM `{$native_table}` WHERE `{$id_col}` = %d AND meta_key = %s", (int) $row[ $id_col ], $field['key'] ) ); + $want = (string) maybe_serialize( TMDO_Type_Caster::from_db( $row[ $col ], $field ) ); + // get_results(), not get_col(): wpdb reads an empty string as null. + $native = array_column( (array) $wpdb->get_results( $wpdb->prepare( "SELECT meta_value FROM `{$native_table}` WHERE `{$id_col}` = %d AND meta_key = %s", (int) $row[ $id_col ], $field['key'] ), ARRAY_A ), 'meta_value' ); if ( array( $want ) !== $native ) { ++$result['mismatches']; } diff --git a/tests/integration/NativeRestorerRetireTest.php b/tests/integration/NativeRestorerRetireTest.php index 4b88f10..cec6483 100644 --- a/tests/integration/NativeRestorerRetireTest.php +++ b/tests/integration/NativeRestorerRetireTest.php @@ -129,6 +129,15 @@ class NativeRestorerRetireTest extends TestCase { $this->assertSame( 3, $result['mismatches'], 't1, ["1.1.1.1"], t2 are not native yet' ); } + public function test_empty_string_values_count_as_written_back(): void { + global $wpdb; + $wpdb->query( 'UPDATE `' . self::A . "` SET ips = '' WHERE user_id = 2" ); + TMDO_Native_Restorer::run( 'user', false, 500, false, 'rt_a' ); + self::register( false ); + + $this->assertSame( 'retired', TMDO_Native_Restorer::retire( 'user', 'rt_a' )['status'], "wpdb::get_col() reads '' as null" ); + } + public function test_retire_forgets_the_group_and_keeps_its_table_as_a_backup(): void { global $wpdb; TMDO_Native_Restorer::run( 'user', false, 500, false, 'rt_a' ); diff --git a/tests/integration/bootstrap.php b/tests/integration/bootstrap.php index 0ab1764..c19554b 100644 --- a/tests/integration/bootstrap.php +++ b/tests/integration/bootstrap.php @@ -129,7 +129,8 @@ $wpdb = new class( $_mysqli ) { public function get_var( string $sql ): ?string { $result = $this->db->query( $sql ); if ( ! $result || ! ( $row = $result->fetch_row() ) ) { return null; } - return $row[0] !== null ? (string) $row[0] : null; + // Like wpdb::get_var(): an empty string reads as null. + return null !== $row[0] && '' !== $row[0] ? (string) $row[0] : null; } public function get_row( string $sql, $output = 'OBJECT' ) { @@ -152,7 +153,8 @@ $wpdb = new class( $_mysqli ) { $result = $this->db->query( $sql ); if ( ! $result ) { return []; } $values = []; - while ( $row = $result->fetch_row() ) { $values[] = $row[ $col_index ] ?? null; } + // Like wpdb::get_col() (per-row get_var()): an empty string reads as null. + while ( $row = $result->fetch_row() ) { $values[] = isset( $row[ $col_index ] ) && '' !== $row[ $col_index ] ? $row[ $col_index ] : null; } return $values; }