Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve generate_cache_key to reduce cache miss while avoiding collision #5347

Open
wants to merge 8 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/wp-includes/class-wp-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -4867,7 +4867,7 @@ static function ( &$value ) use ( $wpdb, $placeholder ) {

// Replace wpdb placeholder in the SQL statement used by the cache key.
$sql = $wpdb->remove_placeholder_escape( $sql );
$key = md5( serialize( $args ) . $sql );
$key = md5( $sql );

$last_changed = wp_cache_get_last_changed( 'posts' );
if ( ! empty( $this->tax_query->queries ) ) {
Expand Down
44 changes: 44 additions & 0 deletions tests/phpunit/tests/query/cacheResults.php
Original file line number Diff line number Diff line change
Expand Up @@ -1418,4 +1418,48 @@ public function test_get_post_meta_lazy_loads_all_term_meta_data() {
// No additional queries expected.
$this->assertSame( 0, $num_queries, 'Unexpected number of queries during second query of term meta.' );
}

/**
* @ticket 59442
*
* @covers WP_Query::generate_cache_key
*/
public function test_generate_cache_key_avoid_args() {
global $wpdb;

$query1 = new WP_Query(
array(
'cache_results' => true,
'fields' => 'ids',
'post_type' => 'post',
)
);

$reflection1 = new ReflectionMethod( $query1, 'generate_cache_key' );
$reflection1->setAccessible( true );
// Cache key with post_type
$cache_key_1 = $reflection1->invoke( $query1, $query1->query_vars, $query1->request );
$reflection1->setAccessible( false );
$num_queries_start = get_num_queries();

// Following query without `post_type` leads to exact same SQL request as query1.
$query2 = new WP_Query(
array(
'cache_results' => true,
'fields' => 'ids',
)
);
$num_queries = get_num_queries() - $num_queries_start;

$reflection2 = new ReflectionMethod( $query2, 'generate_cache_key' );
$reflection2->setAccessible( true );
// Cache key without `post_type`.
$cache_key_2 = $reflection2->invoke( $query2, $query2->query_vars, $query2->request );
$reflection2->setAccessible( false );

// Ensure SQL request formed with and without `post_type` were similar.
$this->assertSame( $query1->request, $query2->request, 'SQL request formed are not similar.' );
$this->assertSame( $cache_key_1, $cache_key_2, 'Cache key differs when `post_type` not passed in args.' );
$this->assertSame( 0, $num_queries, 'Second call executed additional queries.' );
}
}
Loading