test(2meet-data-optimizer): compare site-wide rating sorts by sort key, not id
Tests / PHP Lint (pull_request) Successful in 16s
Anti-EAV Lint + Quality Gate / anti-eav-lint (pull_request) Successful in 16s
Tests / Unit Tests (pull_request) Successful in 45s
Tests / PHPCS (pull_request) Successful in 35s
Tests / Integration Tests (pull_request) Successful in 1m38s
Tests / PHPStan (pull_request) Successful in 1m18s

- The PR-079 live router cases ran the HivePress rating sort on the whole site with an unqualified DECIMAL: native rounds 4.5 to 5 and orders its many ties by chance, so the id order passed or failed with the query plan. They now send DECIMAL(10,1), as the HivePress Rating field does, and compare each position's native sort key and found_posts; the flat-first / GROUP BY assertions stay.
- Verify: live router 18/18 twice; all suites 56/56
- PR: PR-089b
This commit is contained in:
2026-09-27 10:20:30 +08:00
parent edf9e6bc93
commit 582ff13a11
+31 -6
View File
@@ -427,6 +427,7 @@ TMDO_Live::test(
/** /**
* HivePress-style sort-only search (rating__order), fields ids, first page. * HivePress-style sort-only search (rating__order), fields ids, first page.
* DECIMAL(10,1): what the HivePress Rating field (decimals 1) sends.
* *
* @param string $order ASC | DESC. * @param string $order ASC | DESC.
* @return array<string, mixed> WP_Query args. * @return array<string, mixed> WP_Query args.
@@ -441,8 +442,8 @@ function tmdo_live_router_rating_sort( string $order ): array {
'meta_query' => array( 'meta_query' => array(
array( array(
'relation' => 'OR', 'relation' => 'OR',
'rating__order' => array( 'key' => 'hp_rating', 'type' => 'DECIMAL', 'compare' => 'NOT EXISTS' ), 'rating__order' => array( 'key' => 'hp_rating', 'type' => 'DECIMAL(10,1)', 'compare' => 'NOT EXISTS' ),
array( 'key' => 'hp_rating', 'type' => 'DECIMAL', 'compare' => 'EXISTS' ), array( 'key' => 'hp_rating', 'type' => 'DECIMAL(10,1)', 'compare' => 'EXISTS' ),
), ),
), ),
'orderby' => 'rating__order', 'orderby' => 'rating__order',
@@ -450,6 +451,27 @@ function tmdo_live_router_rating_sort( string $order ): array {
); );
} }
/**
* The native sort key of each post, in order (null without a rating). On the
* whole site many listings share a rating and native orders ties by chance,
* so a page is compared by its keys, not its ids.
*
* @param array<int|string> $ids Post ids.
* @return array<int, string|null>
*/
function tmdo_live_router_rating_keys( array $ids ): array {
global $wpdb;
$ids = array_map( 'intval', $ids );
if ( empty( $ids ) ) {
return array();
}
$rows = $wpdb->get_results(
"SELECT post_id, CAST(meta_value AS DECIMAL(10,1)) AS k FROM {$wpdb->postmeta} WHERE meta_key = 'hp_rating' AND post_id IN (" . implode( ',', $ids ) . ')',
OBJECT_K
);
return array_map( static fn( $id ) => isset( $rows[ $id ] ) ? (string) $rows[ $id ]->k : null, $ids );
}
/** /**
* Native and routed runs of the same query. * Native and routed runs of the same query.
* *
@@ -476,7 +498,7 @@ TMDO_Live::test(
TMDO_Post_Query_Router::forget_coverage(); TMDO_Post_Query_Router::forget_coverage();
foreach ( array( 'DESC', 'ASC' ) as $order ) { foreach ( array( 'DESC', 'ASC' ) as $order ) {
list( $native, $routed ) = tmdo_live_router_native_and_routed( tmdo_live_router_rating_sort( $order ) ); list( $native, $routed ) = tmdo_live_router_native_and_routed( tmdo_live_router_rating_sort( $order ) );
tmdo_live_assert_same( array_map( 'intval', $native->posts ), array_map( 'intval', $routed->posts ), "{$order} ids" ); tmdo_live_assert_same( tmdo_live_router_rating_keys( $native->posts ), tmdo_live_router_rating_keys( $routed->posts ), "{$order} sort keys" );
tmdo_live_assert_same( $native->found_posts, $routed->found_posts, "{$order} found_posts" ); tmdo_live_assert_same( $native->found_posts, $routed->found_posts, "{$order} found_posts" );
tmdo_live_assert_true( 0 === strpos( ltrim( $routed->request ), 'SELECT STRAIGHT_JOIN' ), "{$order} flat-first: " . $routed->request ); tmdo_live_assert_true( 0 === strpos( ltrim( $routed->request ), 'SELECT STRAIGHT_JOIN' ), "{$order} flat-first: " . $routed->request );
} }
@@ -497,7 +519,8 @@ TMDO_Live::test(
} finally { } finally {
TMDO_Post_Query_Router::forget_coverage(); TMDO_Post_Query_Router::forget_coverage();
} }
tmdo_live_assert_same( array_map( 'intval', $native->posts ), array_map( 'intval', $routed->posts ), 'ids' ); tmdo_live_assert_same( tmdo_live_router_rating_keys( $native->posts ), tmdo_live_router_rating_keys( $routed->posts ), 'sort keys' );
tmdo_live_assert_same( $native->found_posts, $routed->found_posts, 'found_posts' );
tmdo_live_assert_true( false === strpos( $routed->request, 'STRAIGHT_JOIN' ), 'not flat-first: ' . $routed->request ); tmdo_live_assert_true( false === strpos( $routed->request, 'STRAIGHT_JOIN' ), 'not flat-first: ' . $routed->request );
} }
); );
@@ -532,7 +555,8 @@ TMDO_Live::test(
'tax_query' => array( array( 'taxonomy' => 'hp_listing_category', 'field' => 'term_id', 'terms' => array( 999999999 ), 'operator' => 'NOT IN' ) ), 'tax_query' => array( array( 'taxonomy' => 'hp_listing_category', 'field' => 'term_id', 'terms' => array( 999999999 ), 'operator' => 'NOT IN' ) ),
); );
list( $native, $routed ) = tmdo_live_router_native_and_routed( $args ); list( $native, $routed ) = tmdo_live_router_native_and_routed( $args );
tmdo_live_assert_same( array_map( 'intval', $native->posts ), array_map( 'intval', $routed->posts ), 'ids' ); tmdo_live_assert_same( tmdo_live_router_rating_keys( $native->posts ), tmdo_live_router_rating_keys( $routed->posts ), 'sort keys' );
tmdo_live_assert_same( $native->found_posts, $routed->found_posts, 'found_posts' );
tmdo_live_assert_true( 0 === strpos( ltrim( $routed->request ), 'SELECT STRAIGHT_JOIN' ), 'flat-first: ' . $routed->request ); tmdo_live_assert_true( 0 === strpos( ltrim( $routed->request ), 'SELECT STRAIGHT_JOIN' ), 'flat-first: ' . $routed->request );
tmdo_live_assert_true( false === stripos( $routed->request, 'GROUP BY' ), 'no GROUP BY: ' . $routed->request ); tmdo_live_assert_true( false === stripos( $routed->request, 'GROUP BY' ), 'no GROUP BY: ' . $routed->request );
} }
@@ -552,7 +576,8 @@ TMDO_Live::test(
'tax_query' => array( array( 'taxonomy' => 'hp_listing_category', 'field' => 'term_id', 'terms' => $terms, 'operator' => 'IN' ) ), 'tax_query' => array( array( 'taxonomy' => 'hp_listing_category', 'field' => 'term_id', 'terms' => $terms, 'operator' => 'IN' ) ),
); );
list( $native, $routed ) = tmdo_live_router_native_and_routed( $args ); list( $native, $routed ) = tmdo_live_router_native_and_routed( $args );
tmdo_live_assert_same( array_map( 'intval', $native->posts ), array_map( 'intval', $routed->posts ), 'ids' ); tmdo_live_assert_same( tmdo_live_router_rating_keys( $native->posts ), tmdo_live_router_rating_keys( $routed->posts ), 'sort keys' );
tmdo_live_assert_same( $native->found_posts, $routed->found_posts, 'found_posts' );
tmdo_live_assert_true( false !== stripos( $routed->request, 'GROUP BY' ), 'GROUP BY kept: ' . $routed->request ); tmdo_live_assert_true( false !== stripos( $routed->request, 'GROUP BY' ), 'GROUP BY kept: ' . $routed->request );
} }
); );