Make WordPress Core

Changeset 58122

Timestamp:
05/08/2024 10:49:46 PM (3 months ago)
Author:
spacedmonkey
Message:

Query: Improve cache key generation.

Query caching in WP_Query was added in [53941]. When this functionality was added to the WP_Query class, a number of edge cases were missed that would result in redundant duplicate queries. It was possible to pass parameters to WP_Query that would be different but would result in the same database query being generated. As the cache key is generated from a mixture of query arguments and the SQL query, this resulted in different cache keys for the same database query, resulting in unnecessary duplicate queries. In this change, the logic in the generate_cache_key method has been improved to ensure reuse of existing caches. The following edge cases have been considered:

  • Passing post_type as an empty string.
  • Passing post_type as the string any.
  • Passing post_type as array vs. string.
  • Passing post_type as an array in a different order.
  • Not passing orderby.
  • Passing post_status as an array vs. string.
  • Passing post_status as an array in a different order.

This change also fixes an issue where the old SQL query would not match, as the queries had different whitespaces.

Props spacedmonkey, joemcgill, pbearne, peterwilsoncc, rajinsharwar, mukesh27, thekt12, huzaifaalmesbah, rodionov201.
Fixes #59442.

Location:
trunk
Files:
2 edited

Legend:

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

    r57761 r58122  
    22652265                } elseif ( count( $post_type ) === 1 ) {
    22662266                    $post_type = $post_type[0];
     2267
     2268
     2269
    22672270                }
    22682271
    ���  
    25432546            }
    25442547        } elseif ( ! empty( $post_type ) && is_array( $post_type ) ) {
     2548
     2549
    25452550            $post_type_where = " AND {$wpdb->posts}.post_type IN ('" . implode( "', '", esc_sql( $post_type ) ) . "')";
    25462551        } elseif ( ! empty( $post_type ) ) {
     
    26482653
    26492654            if ( ! empty( $queried_post_types ) ) {
    2650 
     2655                sort( $queried_post_types );
    26512656                $status_type_clauses = array();
    26522657
     
    31053110        }
    31063111
    3107         // Beginning of the string is on a new line to prevent leading whitespace. See https://core.trac.wordpress.org/ticket/56841.
     3112        /*
     3113         * Beginning of the string is on a new line to prevent leading whitespace.
     3114         *
     3115         * The additional indentation of subsequent lines is to ensure the SQL
     3116         * queries are identical to those generated when splitting queries. This
     3117         * improves caching of the query by ensuring the same cache key is
     3118         * generated for the same database queries functionally.
     3119         *
     3120         * See https://core.trac.wordpress.org/ticket/56841.
     3121         * See https://github.com/WordPress/wordpress-develop/pull/6393#issuecomment-2088217429
     3122         */
    31083123        $old_request =
    31093124            "SELECT $found_rows $distinct $fields
    3110             FROM {$wpdb->posts} $join
    3111             WHERE 1=1 $where
    3112             $groupby
    3113             $orderby
    3114             $limits";
     3125            FROM {$wpdb->posts} $join
     3126            WHERE 1=1 $where
     3127            $groupby
     3128            $orderby
     3129            $limits";
    31153130
    31163131        $this->request = $old_request;
     
    48574872        );
    48584873
     4874
     4875
     4876
     4877
     4878
     4879
     4880
     4881
     4882
     4883
     4884
     4885
     4886
     4887
     4888
     4889
     4890
     4891
     4892
     4893
     4894
     4895
     4896
     4897
     4898
     4899
    48594900        $placeholder = $wpdb->placeholder_escape();
    48604901        array_walk_recursive(
     
    48754916        );
    48764917
     4918
     4919
    48774920        // Replace wpdb placeholder in the SQL statement used by the cache key.
    48784921        $sql = $wpdb->remove_placeholder_escape( $sql );
  • trunk/tests/phpunit/tests/query/cacheResults.php

    r56925 r58122  
    170170
    171171        $this->assertSame( $cache_key_1, $cache_key_2, 'Cache key differs when using wpdb placeholder.' );
     172
     173
     174
     175
     176
     177
     178
     179
     180
     181
     182
     183
     184
     185
     186
     187
     188
     189
     190
     191
     192
     193
     194
     195
     196
     197
     198
     199
     200
     201
     202
     203
     204
     205
     206
     207
     208
     209
     210
     211
     212
     213
     214
     215
     216
     217
     218
     219
     220
     221
     222
     223
     224
     225
     226
     227
     228
    172229    }
    173230
     
    218275
    219276    /**
     277
     278
     279
     280
     281
     282
     283
     284
     285
     286
     287
     288
     289
     290
     291
     292
     293
     294
     295
     296
     297
     298
     299
     300
     301
     302
     303
     304
     305
     306
     307
     308
     309
     310
     311
     312
     313
     314
     315
     316
     317
     318
     319
     320
     321
     322
     323
     324
     325
     326
     327
     328
     329
     330
     331
     332
     333
     334
     335
     336
     337
     338
     339
     340
     341
     342
     343
     344
    220345     * Data provider.
    221346     *
     
    262387                    'cache_results' => true,
    263388                    'post_type'     => 'page',
     389
     390
     391
     392
     393
     394
     395
     396
     397
     398
     399
     400
    264401                ),
    265402            ),
Note: See TracChangeset for help on using the changeset viewer.