fix(2meet-data-optimizer): route a meta query only when every registered clause is routable
- Leave the query to WordPress on OR, nested groups with registered keys, several post types, orderby on a named routed clause, and compare/type pairs whose flat-column semantics differ from native (untyped numeric ranges, CHAR on decimals, NUMERIC on text) - Wrap LIKE values as %esc_like%; hook pre_get_posts at priority 1000 so plugin clauses (HivePress) are seen - Verify: wp eval-file tests/live/run.php router (7/7); qbench Q04/Q06/Q08/Q14/Q16 == native on dev36 - PR: PR-060
This commit is contained in:
@@ -78,7 +78,7 @@ class PostQueryRouterTest extends TestCase {
|
||||
$query = $this->make_query( array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=' ),
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=', 'type' => 'NUMERIC' ),
|
||||
),
|
||||
) );
|
||||
$original = $query->get( 'meta_query' );
|
||||
@@ -100,7 +100,7 @@ class PostQueryRouterTest extends TestCase {
|
||||
$query = $this->make_query( array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=' ),
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=', 'type' => 'NUMERIC' ),
|
||||
),
|
||||
) );
|
||||
$original = $query->get( 'meta_query' );
|
||||
@@ -123,7 +123,7 @@ class PostQueryRouterTest extends TestCase {
|
||||
$query = $this->make_query( array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=' ),
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=', 'type' => 'NUMERIC' ),
|
||||
),
|
||||
) );
|
||||
|
||||
@@ -149,7 +149,7 @@ class PostQueryRouterTest extends TestCase {
|
||||
$query = $this->make_query( array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=' ),
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=', 'type' => 'NUMERIC' ),
|
||||
array( 'key' => 'unmanaged_attr', 'value' => 'x' ),
|
||||
),
|
||||
) );
|
||||
@@ -177,7 +177,7 @@ class PostQueryRouterTest extends TestCase {
|
||||
$query = $this->make_query( array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=' ),
|
||||
array( 'key' => '_price', 'value' => '50', 'compare' => '>=', 'type' => 'NUMERIC' ),
|
||||
),
|
||||
) );
|
||||
$original = $query->get( 'meta_query' );
|
||||
@@ -202,7 +202,7 @@ class PostQueryRouterTest extends TestCase {
|
||||
$query = $this->make_query( array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_price', 'value' => '50' ),
|
||||
array( 'key' => '_price', 'value' => '50', 'type' => 'NUMERIC' ),
|
||||
),
|
||||
'wpdo_post_clauses' => array(),
|
||||
) );
|
||||
@@ -221,7 +221,7 @@ class PostQueryRouterTest extends TestCase {
|
||||
$query = $this->make_query( array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_price', 'value' => '99', 'compare' => '=' ),
|
||||
array( 'key' => '_price', 'value' => '99', 'compare' => '=', 'type' => 'NUMERIC' ),
|
||||
),
|
||||
) );
|
||||
|
||||
@@ -242,4 +242,156 @@ class PostQueryRouterTest extends TestCase {
|
||||
|
||||
$this->assertSame( '', $query->get( 'wpdo_post_clauses' ) );
|
||||
}
|
||||
|
||||
// ── all-or-nothing: native unless every registered clause is routable ────
|
||||
|
||||
/**
|
||||
* Run pre_get_posts in aeav_only and assert the query was left to WordPress.
|
||||
*
|
||||
* @param array<string, mixed> $vars Query vars.
|
||||
*/
|
||||
private function assert_not_routed( array $vars, string $why ): void {
|
||||
$this->set_post_mode( 'aeav_only' );
|
||||
$query = $this->make_query( $vars );
|
||||
( new WPDO_Post_Query_Router() )->pre_get_posts( $query );
|
||||
|
||||
$this->assertSame( $vars['meta_query'], $query->get( 'meta_query' ), $why . ': meta_query untouched.' );
|
||||
$this->assertSame( '', $query->get( 'wpdo_post_clauses' ), $why . ': nothing routed.' );
|
||||
}
|
||||
|
||||
public function test_or_relation_is_not_routed(): void {
|
||||
$this->assert_not_routed(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
'relation' => 'OR',
|
||||
array( 'key' => '_stock', 'value' => '1' ),
|
||||
array( 'key' => '_sku', 'value' => 'x' ),
|
||||
),
|
||||
),
|
||||
'OR'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_several_post_types_are_not_routed(): void {
|
||||
$this->assert_not_routed(
|
||||
array(
|
||||
'post_type' => array( 'product', 'post' ),
|
||||
'meta_query' => array( array( 'key' => '_price', 'value' => '5', 'compare' => '>=', 'type' => 'NUMERIC' ) ),
|
||||
),
|
||||
'several post types'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_untyped_range_on_a_numeric_column_is_not_routed(): void {
|
||||
$this->assert_not_routed(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array( array( 'key' => '_price', 'value' => '9000', 'compare' => '>' ) ),
|
||||
),
|
||||
'CHAR > on DECIMAL'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_untyped_equality_on_a_decimal_column_is_not_routed(): void {
|
||||
$this->assert_not_routed(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array( array( 'key' => '_price', 'value' => '10' ) ),
|
||||
),
|
||||
'CHAR = on DECIMAL (native "10.00" != "10")'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_numeric_type_on_a_text_column_is_not_routed(): void {
|
||||
$this->assert_not_routed(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array( array( 'key' => '_sku', 'value' => '5', 'compare' => '>', 'type' => 'NUMERIC' ) ),
|
||||
),
|
||||
'NUMERIC on VARCHAR'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_unknown_compare_is_not_routed(): void {
|
||||
$this->assert_not_routed(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array( array( 'key' => '_sku', 'value' => '^a', 'compare' => 'REGEXP' ) ),
|
||||
),
|
||||
'REGEXP'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_one_unroutable_registered_clause_keeps_the_whole_query_native(): void {
|
||||
$this->assert_not_routed(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_stock', 'value' => '3', 'compare' => '>=', 'type' => 'NUMERIC' ),
|
||||
array( 'key' => '_price', 'value' => '9000', 'compare' => '>' ),
|
||||
),
|
||||
),
|
||||
'one unroutable clause'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_nested_group_with_a_registered_key_is_not_routed(): void {
|
||||
$this->assert_not_routed(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_stock', 'value' => '3', 'compare' => '>=', 'type' => 'NUMERIC' ),
|
||||
array(
|
||||
'relation' => 'OR',
|
||||
array( 'key' => '_price', 'compare' => 'NOT EXISTS' ),
|
||||
array( 'key' => '_price', 'compare' => 'EXISTS' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
'nested group'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_orderby_on_a_named_registered_clause_is_not_routed(): void {
|
||||
$this->assert_not_routed(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array( 'price' => array( 'key' => '_price', 'compare' => 'EXISTS', 'type' => 'NUMERIC' ) ),
|
||||
'orderby' => array( 'price' => 'ASC' ),
|
||||
),
|
||||
'orderby names a routed clause'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_untyped_integer_equality_on_an_integer_column_is_routed(): void {
|
||||
$this->set_post_mode( 'aeav_only' );
|
||||
$query = $this->make_query(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array(
|
||||
array( 'key' => '_stock', 'value' => '3' ),
|
||||
array( 'key' => 'unmanaged_attr', 'value' => 'x' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
( new WPDO_Post_Query_Router() )->pre_get_posts( $query );
|
||||
|
||||
$this->assertNotEmpty( $query->get( 'wpdo_post_clauses' ) );
|
||||
$this->assertCount( 1, $query->get( 'meta_query' ), 'unregistered AND clause stays native' );
|
||||
}
|
||||
|
||||
public function test_like_matches_an_escaped_substring(): void {
|
||||
$this->set_post_mode( 'aeav_only' );
|
||||
$router = new WPDO_Post_Query_Router();
|
||||
$query = $this->make_query(
|
||||
array(
|
||||
'post_type' => 'product',
|
||||
'meta_query' => array( array( 'key' => '_sku', 'value' => 'B1_1%', 'compare' => 'LIKE' ) ),
|
||||
)
|
||||
);
|
||||
$router->pre_get_posts( $query );
|
||||
|
||||
$this->assertStringContainsString( "LIKE '%B1\\\\_1\\\\%%'", $router->posts_where( '', $query ) );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user