[wp-trac] [WordPress Trac] #56802: Query: Post IDs cached for search and other 'LIKE' queries are unreachable
WordPress Trac
noreply at wordpress.org
Tue Oct 11 18:07:50 UTC 2022
#56802: Query: Post IDs cached for search and other 'LIKE' queries are unreachable
--------------------------+------------------------------
Reporter: dlh | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Query | Version: trunk
Severity: normal | Resolution:
Keywords: | Focuses:
--------------------------+------------------------------
Description changed by dlh:
Old description:
> [53941] added caching for the post ID database query in `WP_Query`. The
> cache key for the post IDs is determined by hashing (among other details)
> the `$request` property of the query, which contains the generated SQL.
>
> At the time that this cache key is generated, the SQL in `$request` still
> contains escaped placeholders from `wpdb::add_placeholder_escape()`. For
> example:
>
> {{{
> SELECT SQL_CALC_FOUND_ROWS wp_posts.*
> FROM wp_posts
> WHERE 1=1 AND (((wp_posts.post_title LIKE
> '{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}hello{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}')
> OR (wp_posts.post_excerpt LIKE
> '{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}hello{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}')
> OR (wp_posts.post_content LIKE
> '{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}hello{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}')))
> AND ((wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish'
> OR wp_posts.post_status = 'private')) OR (wp_posts.post_type = 'page' AND
> (wp_posts.post_status = 'publish'
> OR wp_posts.post_status = 'private')) OR (wp_posts.post_type =
> 'attachment' AND (wp_posts.post_status = 'publish'
> OR wp_posts.post_status = 'private')))
>
> ORDER BY wp_posts.post_title LIKE
> '{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}hello{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}'
> DESC, wp_posts.post_date DESC
> LIMIT 0, 10
> }}}
>
> `wpdb` generates this placeholder once per request using `uniqid()`,
> making it unlikely that the placeholder will be the same across multiple
> requests.
>
> As a result, the same search will generate different cache keys on each
> request, since the SQL will differ along with the placeholder. The IDs
> will be cached, but that cache will probably never be found.
>
> From what I can tell, this issue affects search queries (with `s`) and
> meta queries that use `'compare' => 'LIKE'` or `'compare_key' => 'LIKE'`
> (or `NOT LIKE`). Presumably, any other queries that include placeholders
> and use `wpdb::prepare()` would also be affected.
>
> I'm not quite sure what the best course for the issue would. My first
> thought was to expand, in `WP_Query`,
>
> `$id_query_is_cacheable = ! str_contains( strtoupper( $orderby ), '
> RAND(' );`
>
> to include
>
> `&& ! str_contains( $this->request, $wpdb->placeholder_escape() )`
>
> However, calling `wpdb::placeholder_escape()` has a side-effect of adding
> a filter to `query`, and that might not be desirable.
>
> Perhaps a naive check like `! str_contains( $this->request, " LIKE '{" )`
> would do the trick, but it's possible that that would catch unrelated
> queries.
New description:
[53941] added caching for the post ID database query in `WP_Query`. The
cache key for the post IDs is determined by hashing (among other details)
the `$request` property of the query, which contains the generated SQL.
At the time that this cache key is generated, the SQL in `$request` still
contains escaped placeholders from `wpdb::add_placeholder_escape()`. For
example:
{{{
SELECT SQL_CALC_FOUND_ROWS wp_posts.*
FROM wp_posts
WHERE 1=1 AND (((wp_posts.post_title LIKE
'{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}hello{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}')
OR (wp_posts.post_excerpt LIKE
'{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}hello{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}')
OR (wp_posts.post_content LIKE
'{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}hello{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}')))
AND ((wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private')) OR (wp_posts.post_type = 'page' AND
(wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private')) OR (wp_posts.post_type =
'attachment' AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private')))
ORDER BY wp_posts.post_title LIKE
'{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}hello{6bf47a1ba3fa507a5e63620d433b08dd0a8c3664854a451088b2fd023cb1d0f0}'
DESC, wp_posts.post_date DESC
LIMIT 0, 10
}}}
`wpdb` generates this placeholder once per request using `uniqid()`,
making it unlikely that the placeholder will be the same across multiple
requests.
As a result, the same search will generate different cache keys on each
request, since the SQL will differ along with the placeholder. The IDs
will be cached, but that cache will probably never be found.
From what I can tell, this issue affects search queries (with `'s'`) and
meta queries that use `'compare' => 'LIKE'` or `'compare_key' => 'LIKE'`
(or `NOT LIKE`). Presumably, any other queries that include placeholders
and use `wpdb::prepare()` would also be affected.
I'm not quite sure what the best course for the issue would be. My first
thought was to expand, in `WP_Query`,
`$id_query_is_cacheable = ! str_contains( strtoupper( $orderby ), ' RAND('
);`
to include
`&& ! str_contains( $this->request, $wpdb->placeholder_escape() )`
However, calling `wpdb::placeholder_escape()` has a side-effect of adding
a filter to `query`, and that might not be desirable.
Perhaps a naive check like `! str_contains( $this->request, " LIKE '{" )`
would do the trick, but it's possible that that would catch unrelated
queries.
--
--
Ticket URL: <https://core.trac.wordpress.org/ticket/56802#comment:1>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list