WordPress.org

Make WordPress Core

Changeset 39564


Ignore:
Timestamp:
12/11/16 21:42:12 (10 months ago)
Author:
peterwilsoncc
Message:

Options: Prevent unnecessary SQL updates by update_option.

Previously an option containing an object would trigger an SQL UPDATE on all calls to update_option, even if the old and new values were identical. This was due to the old and new values having differing resource IDs.

This change compares the old and new values as serialized data to remove the resource ID from the comparison.

Props salcode, bradyvercher, peterwilsoncc.
Fixes #38903.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/option.php

    r39470 r39564  
    296296    $value = apply_filters( 'pre_update_option', $value, $option, $old_value ); 
    297297 
    298     // If the new and old values are the same, no need to update. 
    299     if ( $value === $old_value ) 
     298    /* 
     299     * If the new and old values are the same, no need to update. 
     300     * 
     301     * Unserialized values will be adequate in most cases. If the unserialized 
     302     * data differs, the (maybe) serialized data is checked to avoid 
     303     * unnecessary database calls for otherwise identical object instances. 
     304     * 
     305     * See https://core.trac.wordpress.org/ticket/38903 
     306     */ 
     307    if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) { 
    300308        return false; 
     309    } 
    301310 
    302311    /** This filter is documented in wp-includes/option.php */ 
  • trunk/tests/phpunit/tests/option/updateOption.php

    r37954 r39564  
    167167 
    168168    /** 
     169     * @ticket 38903 
     170     */ 
     171    public function test_update_option_array_with_object() { 
     172        $array_w_object = array( 
     173            'url'       => 'http://src.wordpress-develop.dev/wp-content/uploads/2016/10/cropped-Blurry-Lights.jpg', 
     174            'meta_data' => (object) array( 
     175                'attachment_id' => 292, 
     176                'height'        => 708, 
     177                'width'         => 1260, 
     178            ), 
     179        ); 
     180 
     181        // Add the option, it did not exist before this. 
     182        add_option( 'array_w_object', $array_w_object ); 
     183 
     184        $num_queries_pre_update = get_num_queries(); 
     185 
     186        // Update the option using the same array with an object for the value. 
     187        $this->assertFalse( update_option( 'array_w_object', $array_w_object ) ); 
     188 
     189        // Check that no new database queries were performed. 
     190        $this->assertEquals( $num_queries_pre_update, get_num_queries() ); 
     191    } 
     192 
     193    /** 
    169194     * `add_filter()` callback for test_should_respect_default_option_filter_when_option_does_not_yet_exist_in_database(). 
    170195     */ 
Note: See TracChangeset for help on using the changeset viewer.