-
Notifications
You must be signed in to change notification settings - Fork 3.7k
WP_Query: force deterministic ordering #10262
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
Open
ramonjd
wants to merge
36
commits into
WordPress:trunk
Choose a base branch
from
ramonjd:try/add-id-for-deterministic-ordering-to-prevent-duplicate-records
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
a9a0061
Enhance WP_Query ordering to ensure deterministic results by adding I…
ramonjd 1131f24
WHITESPACE! Oh no!
ramonjd af63e0e
Refactor WP_Query ordering logic to ensure consistent results by appe…
ramonjd fcdb726
Consolidate ID tie-breaker logic and ensure consistent SQL output in …
ramonjd 0245f46
whitespace in unit test
ramonjd eb78345
Refine WP_Query ordering logic to handle 'none' in orderby scenarios …
ramonjd e0f7528
lint
ramonjd 6f8bc1a
Remove ticket number in tests for now
ramonjd ebd9bd2
Refactor WP_Query to ensure consistent ordering by appending ID as a …
ramonjd addb896
Enhance WP_Query ordering logic by normalizing 'date' to 'date, ID' f…
ramonjd 310360e
lint
ramonjd 5a9ef90
linto
ramonjd 9dd9d7b
Fix date formatting in deterministic ordering test to ensure consiste…
ramonjd f2963de
Refactor deterministic ordering tests to utilize shared fixtures for …
ramonjd c29cb0f
Refactor WP_Query ordering logic to implement a blacklist approach fo…
ramonjd 828a90e
Add search relevance tests to deterministic ordering suite
ramonjd e9df9e1
Enhance WP_Query ordering by adding new fields to the orderby array. …
ramonjd 3d355d7
Implement deterministic ordering in WP_Query by adding ID tie-breaker…
ramonjd fbe02ee
lint
ramonjd 8ab6a79
Refactor REST API post ordering tests to remove ID tie-breaker from a…
ramonjd 8183228
Refactor WP_Query to preserve filter modifications to orderby. Adjust…
ramonjd 4896bca
Separate units in tests for posts_orderby and posts_clauses filter be…
ramonjd 3bf4883
Query: build the ID tie-breaker before the query clause filters run.
ramonjd 1a468a0
Query: restore the cache key's default orderby value.
ramonjd 25f35b5
Query: restore the cache key's SELECT field replacement.
ramonjd 2cd22a7
Tests: cover paginated queries returning a post more than once.
ramonjd 7f4bb49
Query: only normalise the selected columns in the cache key.
ramonjd dfeea0f
Docs: record the version the ordering change landed in.
ramonjd df7897c
Query: match parse_orderby() when spotting a seeded RAND.
ramonjd e1d23b9
Tests: cover media pagination ordered by a shared column.
ramonjd fb944c6
Query: track the tie-breaker's direction instead of parsing it back out.
ramonjd fc8c389
Query: describe the ID clause the way WP_Comment_Query does.
ramonjd e6945a5
Query: append the ID clause to parent and slug list orderings too.
ramonjd e6b9b3d
Query: only blank the ORDER BY when 'none' is the whole ordering.
ramonjd 933c759
Query: keep an all-invalid array 'orderby' unordered, as on trunk.
ramonjd 6366ed1
Tests: cover meta ordering and page pagination; tighten the assertions.
ramonjd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,7 +99,15 @@ public function test_columns_should_be_sortable( $order, $orderby, $search, $exp | |
| unset( $_REQUEST['orderby'] ); | ||
| unset( $_REQUEST['s'] ); | ||
|
|
||
| $this->assertStringContainsString( "ORDER BY {$wpdb->posts}.{$expected}", $this->sql ); | ||
| $expected_query = explode( ', ', $expected ); | ||
| $expected_query = array_map( | ||
| function ( $item ) use ( $wpdb ) { | ||
| return "{$wpdb->posts}.{$item}"; | ||
| }, | ||
| $expected_query | ||
| ); | ||
|
|
||
| $this->assertStringContainsString( 'ORDER BY ' . implode( ', ', $expected_query ), $this->sql ); | ||
|
Comment on lines
+102
to
+110
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the expected string now holds two columns but the old assertion prepended |
||
| } | ||
|
|
||
| /** | ||
|
|
@@ -136,42 +144,42 @@ public function data_columns_should_be_sortable() { | |
| 'order' => null, | ||
| 'orderby' => null, | ||
| 's' => null, | ||
| 'expected' => 'post_date DESC', | ||
| 'expected' => 'post_date DESC, ID DESC', | ||
| ), | ||
| // Default order (ID) DESC. | ||
| array( | ||
| 'order' => '', | ||
| 'orderby' => '', | ||
| 's' => '', | ||
| 'expected' => 'post_date DESC', | ||
| 'expected' => 'post_date DESC, ID DESC', | ||
| ), | ||
| // Order by requester (post_title) ASC. | ||
| array( | ||
| 'order' => 'ASC', | ||
| 'orderby' => 'requester', | ||
| 's' => '', | ||
| 'expected' => 'post_title ASC', | ||
| 'expected' => 'post_title ASC, ID ASC', | ||
| ), | ||
| // Order by requester (post_title) DESC. | ||
| array( | ||
| 'order' => 'DESC', | ||
| 'orderby' => 'requester', | ||
| 's' => null, | ||
| 'expected' => 'post_title DESC', | ||
| 'expected' => 'post_title DESC, ID DESC', | ||
| ), | ||
| // Order by requested (post_date) ASC. | ||
| array( | ||
| 'order' => 'ASC', | ||
| 'orderby' => 'requested', | ||
| 's' => null, | ||
| 'expected' => 'post_date ASC', | ||
| 'expected' => 'post_date ASC, ID ASC', | ||
| ), | ||
| // Order by requested (post_date) DESC. | ||
| array( | ||
| 'order' => 'DESC', | ||
| 'orderby' => 'requested', | ||
| 's' => null, | ||
| 'expected' => 'post_date DESC', | ||
| 'expected' => 'post_date DESC, ID DESC', | ||
| ), | ||
| // Search and order by relevance. | ||
| array( | ||
|
|
@@ -185,14 +193,14 @@ public function data_columns_should_be_sortable() { | |
| 'order' => 'ASC', | ||
| 'orderby' => 'requester', | ||
| 's' => 'foo', | ||
| 'expected' => 'post_title ASC', | ||
| 'expected' => 'post_title ASC, ID ASC', | ||
| ), | ||
| // Search and order by requested (post_date) ASC. | ||
| array( | ||
| 'order' => 'ASC', | ||
| 'orderby' => 'requested', | ||
| 's' => 'foo', | ||
| 'expected' => 'post_date ASC', | ||
| 'expected' => 'post_date ASC, ID ASC', | ||
| ), | ||
| ); | ||
| } | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@peterwilsoncc When you get a spare moment (can be after 6.9 or whenever you have head space) could you sanity check this approach for me?
The TL;DR is:
When multiple posts have identical values for the primary sort field (like post_date, post_title, menu_order), the database doesn't guarantee consistent ordering across pagination.
This causes inconsistent pagination results, mainly in the form of dupes.
The solution here (and in all the other attempts from 6 years ago) has been to automatically add ID as a secondary sort field when ordering by fields that can have duplicate values. This ensures records with identical primary sort values always appear in the same order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll also need to consider seeded
RAND, seewordpress-develop/src/wp-includes/class-wp-query.php
Lines 1732 to 1738 in 56868f8