WordPress.org

Make WordPress Core

Changeset 39564


Ignore:
Timestamp:
12/11/2016 09:42:12 PM (18 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.