fix(2meet-data-optimizer): keep meta_key native when the query still orders by it

- meta_key is routed as EXISTS only when no orderby entry names meta_value,
  meta_value_num or the key (several orderings or an array included);
  clearing it made WordPress drop the price ordering
- A sort group is dropped as unused only when orderby names neither it,
  meta_value(_num) nor its key (it is then the primary clause)
- meta_compare_key other than '=' keeps meta_key native (LIKE matches other keys)
- Found in the 2.4 correctness review (regressions from PR-122)
- Verify: PostQueryRouterTest (3 new), router suites 67 OK
- PR: PR-130
This commit is contained in:
2026-09-28 00:27:56 +08:00
parent 7ad65eab95
commit bed3f906da
2 changed files with 72 additions and 8 deletions
+55
View File
@@ -471,6 +471,61 @@ class PostQueryRouterTest extends TestCase {
$this->assertStringContainsString( 'BETWEEN', $where );
}
/**
* WordPress orders by the primary meta clause (meta_key) for meta_value,
* meta_value_num or the key's name anywhere in orderby; routing the key and
* clearing meta_key would drop that ordering (2.4 correctness review).
*/
public function test_meta_key_ordered_by_among_several_orderings_stays_native(): void {
foreach ( array(
array( 'meta_value_num' => 'ASC', 'title' => 'ASC' ),
'meta_value date',
'_stock',
) as $orderby ) {
$this->set_post_mode( 'aeav_only' );
$query = $this->make_query( array( 'post_type' => 'product', 'meta_key' => '_stock', 'orderby' => $orderby ) );
( new WPDO_Post_Query_Router() )->pre_get_posts( $query );
$label = is_array( $orderby ) ? implode( ',', array_keys( $orderby ) ) : $orderby;
$this->assertSame( '_stock', $query->get( 'meta_key' ), $label );
$this->assertSame( '', $query->get( 'wpdo_post_clauses' ), $label );
}
}
/** meta_compare_key LIKE matches other keys too: not a test on one flat column. */
public function test_meta_key_with_a_key_comparison_stays_native(): void {
foreach ( array( 'rand', 'meta_value_num' ) as $orderby ) {
$this->set_post_mode( 'aeav_only' );
$query = $this->make_query( array( 'post_type' => 'product', 'meta_key' => '_stock', 'meta_compare_key' => 'LIKE', 'orderby' => $orderby ) );
( new WPDO_Post_Query_Router() )->pre_get_posts( $query );
$this->assertSame( '_stock', $query->get( 'meta_key' ), $orderby );
$this->assertSame( '', $query->get( 'wpdo_post_clauses' ), $orderby );
}
}
/**
* Without meta_key the first clause is WordPress's primary one: orderby
* meta_value_num sorts by the sort group's key, so the group stays.
*/
public function test_sort_group_ordered_as_the_primary_clause_is_not_dropped(): void {
$this->assert_not_routed(
array(
'post_type' => 'product',
'orderby' => 'meta_value_num',
'meta_query' => array(
array(
'relation' => 'OR',
'price__order' => array( 'key' => '_price', 'compare' => 'NOT EXISTS', 'type' => 'DECIMAL' ),
array( 'key' => '_price', 'compare' => 'EXISTS', 'type' => 'DECIMAL' ),
),
array( 'key' => '_stock', 'value' => 1, 'compare' => '>=', 'type' => 'NUMERIC' ),
),
),
'primary sort group'
);
}
public function test_meta_key_with_a_value_is_left_alone(): void {
$this->set_post_mode( 'aeav_only' );
$router = new WPDO_Post_Query_Router();