Make WordPress Core


Ignore:
Timestamp:
10/17/2014 08:20:04 PM (10 years ago)
Author:
boonebgorges
Message:

Overhaul SQL generating logic in WP_Meta_Query to avoid unnecessary table joins.

The logic used to generate clause SQL in WP_Meta_Query is somewhat arcane,
stemming mostly from an ongoing effort to eliminate costly table joins when
they are not necessary. By systematizing the process of looking for shareable
joins - as was done in WP_Tax_Query [29902] - it becomes possible to simplify
the construction of SQL queries in get_sql_for_clause(). Moreover, the
simplified logic is actually considerably better at identifying shareable
joins, such that certain uses of WP_Meta_Query will see joins reduced by 50%
or more.

Includes integration tests for a representative cross-section of the query
clause combinations that result in shared table aliases.

Props boonebgorges, sc0ttkclark.
See #24093.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/post/query.php

    r29902 r29940  
    648648
    649649    /**
     650     * @ticket 24093
     651     */
     652    public function test_meta_query_relation_or_compare_equals() {
     653        $posts = $this->factory->post->create_many( 4 );
     654        add_post_meta( $posts[0], 'color', 'orange' );
     655        add_post_meta( $posts[1], 'color', 'blue' );
     656        add_post_meta( $posts[1], 'vegetable', 'onion' );
     657        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     658
     659        $query = new WP_Query( array(
     660            'meta_query' => array(
     661                'relation' => 'OR',
     662                array(
     663                    'key' => 'vegetable',
     664                    'value' => 'onion',
     665                    'compare' => '=',
     666                ),
     667                array(
     668                    'key' => 'vegetable',
     669                    'value' => 'shallot',
     670                    'compare' => '=',
     671                ),
     672            ),
     673            'update_post_meta_cache' => false,
     674            'update_post_term_cache' => false,
     675            'fields' => 'ids',
     676        ) );
     677
     678        $expected = array( $posts[1], $posts[2] );
     679        $this->assertEqualSets( $expected, $query->posts );
     680    }
     681
     682    /**
     683     * @ticket 24093
     684     */
     685    public function test_meta_query_relation_or_compare_equals_different_keys() {
     686        $posts = $this->factory->post->create_many( 4 );
     687        add_post_meta( $posts[0], 'color', 'orange' );
     688        add_post_meta( $posts[1], 'color', 'blue' );
     689        add_post_meta( $posts[1], 'vegetable', 'onion' );
     690        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     691
     692        $query = new WP_Query( array(
     693            'meta_query' => array(
     694                'relation' => 'OR',
     695                array(
     696                    'key' => 'vegetable',
     697                    'value' => 'onion',
     698                    'compare' => '=',
     699                ),
     700                array(
     701                    'key' => 'color',
     702                    'value' => 'orange',
     703                    'compare' => '=',
     704                ),
     705            ),
     706            'update_post_meta_cache' => false,
     707            'update_post_term_cache' => false,
     708            'fields' => 'ids',
     709        ) );
     710
     711        $expected = array( $posts[0], $posts[1] );
     712        $this->assertEqualSets( $expected, $query->posts );
     713    }
     714
     715    /**
     716     * @ticket 24093
     717     */
     718    public function test_meta_query_relation_or_compare_equals_and_in() {
     719        $posts = $this->factory->post->create_many( 4 );
     720        add_post_meta( $posts[0], 'color', 'orange' );
     721        add_post_meta( $posts[1], 'color', 'blue' );
     722        add_post_meta( $posts[1], 'vegetable', 'onion' );
     723        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     724
     725        $query = new WP_Query( array(
     726            'meta_query' => array(
     727                'relation' => 'OR',
     728                array(
     729                    'key' => 'vegetable',
     730                    'value' => 'onion',
     731                    'compare' => '=',
     732                ),
     733                array(
     734                    'key' => 'color',
     735                    'value' => array( 'orange', 'green' ),
     736                    'compare' => 'IN',
     737                ),
     738            ),
     739            'update_post_meta_cache' => false,
     740            'update_post_term_cache' => false,
     741            'fields' => 'ids',
     742        ) );
     743
     744        $expected = array( $posts[0], $posts[1] );
     745        $this->assertEqualSets( $expected, $query->posts );
     746    }
     747
     748    /**
     749     * @ticket 24093
     750     */
     751    public function test_meta_query_relation_or_compare_equals_and_like() {
     752        $posts = $this->factory->post->create_many( 4 );
     753        add_post_meta( $posts[0], 'color', 'orange' );
     754        add_post_meta( $posts[1], 'color', 'blue' );
     755        add_post_meta( $posts[1], 'vegetable', 'onion' );
     756        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     757
     758        $query = new WP_Query( array(
     759            'meta_query' => array(
     760                'relation' => 'OR',
     761                array(
     762                    'key' => 'vegetable',
     763                    'value' => 'onion',
     764                    'compare' => '=',
     765                ),
     766                array(
     767                    'key' => 'vegetable',
     768                    'value' => 'hall',
     769                    'compare' => 'LIKE',
     770                ),
     771            ),
     772            'update_post_meta_cache' => false,
     773            'update_post_term_cache' => false,
     774            'fields' => 'ids',
     775        ) );
     776
     777        $expected = array( $posts[1], $posts[2] );
     778        $this->assertEqualSets( $expected, $query->posts );
     779    }
     780
     781    /**
     782     * @ticket 24093
     783     */
     784    public function test_meta_query_relation_or_compare_equals_and_between() {
     785        $posts = $this->factory->post->create_many( 4 );
     786        add_post_meta( $posts[0], 'number_of_colors', '2' );
     787        add_post_meta( $posts[1], 'number_of_colors', '5' );
     788        add_post_meta( $posts[1], 'vegetable', 'onion' );
     789        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     790
     791        $query = new WP_Query( array(
     792            'meta_query' => array(
     793                'relation' => 'OR',
     794                array(
     795                    'key' => 'vegetable',
     796                    'value' => 'shallot',
     797                    'compare' => '=',
     798                ),
     799                array(
     800                    'key' => 'number_of_colors',
     801                    'value' => array( 1, 3 ),
     802                    'compare' => 'BETWEEN',
     803                    'type' => 'SIGNED',
     804                ),
     805            ),
     806            'update_post_meta_cache' => false,
     807            'update_post_term_cache' => false,
     808            'fields' => 'ids',
     809        ) );
     810
     811        $expected = array( $posts[0], $posts[2] );
     812        $this->assertEqualSets( $expected, $query->posts );
     813    }
     814
     815    /**
     816     * @ticket 24093
     817     */
     818    public function test_meta_query_relation_and_compare_in_same_keys() {
     819        $posts = $this->factory->post->create_many( 4 );
     820        add_post_meta( $posts[0], 'color', 'orange' );
     821        add_post_meta( $posts[1], 'color', 'blue' );
     822        add_post_meta( $posts[1], 'vegetable', 'onion' );
     823        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     824        add_post_meta( $posts[3], 'vegetable', 'banana' );
     825        add_post_meta( $posts[3], 'vegetable', 'onion' );
     826
     827        $query = new WP_Query( array(
     828            'meta_query' => array(
     829                'relation' => 'AND',
     830                array(
     831                    'key' => 'vegetable',
     832                    'value' => array( 'onion', 'shallot' ),
     833                    'compare' => 'IN',
     834                ),
     835                array(
     836                    'key' => 'vegetable',
     837                    'value' => array( 'banana' ),
     838                    'compare' => 'IN',
     839                ),
     840            ),
     841            'update_post_meta_cache' => false,
     842            'update_post_term_cache' => false,
     843            'fields' => 'ids',
     844        ) );
     845
     846        $expected = array( $posts[3] );
     847        $this->assertEqualSets( $expected, $query->posts );
     848    }
     849
     850    /**
     851     * @ticket 24093
     852     */
     853    public function test_meta_query_relation_and_compare_in_different_keys() {
     854        $posts = $this->factory->post->create_many( 4 );
     855        add_post_meta( $posts[0], 'color', 'orange' );
     856        add_post_meta( $posts[1], 'color', 'blue' );
     857        add_post_meta( $posts[1], 'vegetable', 'onion' );
     858        add_post_meta( $posts[1], 'vegetable', 'shallot' );
     859        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     860        add_post_meta( $posts[3], 'vegetable', 'banana' );
     861
     862        $query = new WP_Query( array(
     863            'meta_query' => array(
     864                'relation' => 'AND',
     865                array(
     866                    'key' => 'vegetable',
     867                    'value' => array( 'onion', 'shallot' ),
     868                    'compare' => 'IN',
     869                ),
     870                array(
     871                    'key' => 'color',
     872                    'value' => array( 'blue' ),
     873                    'compare' => 'IN',
     874                ),
     875            ),
     876            'update_post_meta_cache' => false,
     877            'update_post_term_cache' => false,
     878            'fields' => 'ids',
     879        ) );
     880
     881        $expected = array( $posts[1] );
     882        $this->assertEqualSets( $expected, $query->posts );
     883    }
     884
     885    /**
     886     * @ticket 24093
     887     */
     888    public function test_meta_query_relation_and_compare_not_equals() {
     889        $posts = $this->factory->post->create_many( 4 );
     890        add_post_meta( $posts[0], 'color', 'orange' );
     891        add_post_meta( $posts[1], 'color', 'blue' );
     892        add_post_meta( $posts[1], 'vegetable', 'onion' );
     893        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     894        add_post_meta( $posts[3], 'vegetable', 'banana' );
     895
     896        $query = new WP_Query( array(
     897            'meta_query' => array(
     898                'relation' => 'AND',
     899                array(
     900                    'key' => 'vegetable',
     901                    'value' => 'onion',
     902                    'compare' => '!=',
     903                ),
     904                array(
     905                    'key' => 'vegetable',
     906                    'value' => 'shallot',
     907                    'compare' => '!=',
     908                ),
     909            ),
     910            'update_post_meta_cache' => false,
     911            'update_post_term_cache' => false,
     912            'fields' => 'ids',
     913        ) );
     914
     915        $expected = array( $posts[3] );
     916        $this->assertEqualSets( $expected, $query->posts );
     917    }
     918
     919    /**
     920     * @ticket 24093
     921     */
     922    public function test_meta_query_relation_and_compare_not_equals_different_keys() {
     923        $posts = $this->factory->post->create_many( 4 );
     924
     925        // !shallot, but orange.
     926        add_post_meta( $posts[0], 'color', 'orange' );
     927        add_post_meta( $posts[0], 'vegetable', 'onion' );
     928
     929        // !orange, but shallot.
     930        add_post_meta( $posts[1], 'color', 'blue' );
     931        add_post_meta( $posts[1], 'vegetable', 'shallot' );
     932
     933        // Neither.
     934        add_post_meta( $posts[2], 'color', 'blue' );
     935        add_post_meta( $posts[2], 'vegetable', 'onion' );
     936
     937        $query = new WP_Query( array(
     938            'meta_query' => array(
     939                'relation' => 'AND',
     940                array(
     941                    'key' => 'vegetable',
     942                    'value' => 'shallot',
     943                    'compare' => '!=',
     944                ),
     945                array(
     946                    'key' => 'color',
     947                    'value' => 'orange',
     948                    'compare' => '!=',
     949                ),
     950            ),
     951            'update_post_meta_cache' => false,
     952            'update_post_term_cache' => false,
     953            'fields' => 'ids',
     954        ) );
     955
     956        $expected = array( $posts[2] );
     957        $this->assertEqualSets( $expected, $query->posts );
     958    }
     959
     960    /**
     961     * @ticket 24093
     962     */
     963    public function test_meta_query_relation_and_compare_not_equals_not_in() {
     964        $posts = $this->factory->post->create_many( 4 );
     965        add_post_meta( $posts[0], 'color', 'orange' );
     966        add_post_meta( $posts[1], 'color', 'blue' );
     967        add_post_meta( $posts[1], 'vegetable', 'onion' );
     968        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     969        add_post_meta( $posts[3], 'vegetable', 'banana' );
     970
     971        $query = new WP_Query( array(
     972            'meta_query' => array(
     973                'relation' => 'AND',
     974                array(
     975                    'key' => 'vegetable',
     976                    'value' => 'onion',
     977                    'compare' => '!=',
     978                ),
     979                array(
     980                    'key' => 'vegetable',
     981                    'value' => array( 'shallot' ),
     982                    'compare' => 'NOT IN',
     983                ),
     984            ),
     985            'update_post_meta_cache' => false,
     986            'update_post_term_cache' => false,
     987            'fields' => 'ids',
     988        ) );
     989
     990        $expected = array( $posts[3] );
     991        $this->assertEqualSets( $expected, $query->posts );
     992    }
     993
     994    /**
     995     * @ticket 24093
     996     */
     997    public function test_meta_query_relation_and_compare_not_equals_and_not_like() {
     998        $posts = $this->factory->post->create_many( 4 );
     999        add_post_meta( $posts[0], 'color', 'orange' );
     1000        add_post_meta( $posts[1], 'color', 'blue' );
     1001        add_post_meta( $posts[1], 'vegetable', 'onion' );
     1002        add_post_meta( $posts[2], 'vegetable', 'shallot' );
     1003        add_post_meta( $posts[3], 'vegetable', 'banana' );
     1004
     1005        $query = new WP_Query( array(
     1006            'meta_query' => array(
     1007                'relation' => 'AND',
     1008                array(
     1009                    'key' => 'vegetable',
     1010                    'value' => 'onion',
     1011                    'compare' => '!=',
     1012                ),
     1013                array(
     1014                    'key' => 'vegetable',
     1015                    'value' => 'hall',
     1016                    'compare' => 'NOT LIKE',
     1017                ),
     1018            ),
     1019            'update_post_meta_cache' => false,
     1020            'update_post_term_cache' => false,
     1021            'fields' => 'ids',
     1022        ) );
     1023
     1024        $expected = array( $posts[3] );
     1025        $this->assertEqualSets( $expected, $query->posts );
     1026    }
     1027
     1028    /**
    6501029     * @ticket 23033
    6511030     * @group meta
     
    10411420        add_post_meta( $post_id6, 'baz', 0 );
    10421421
    1043         $posts = get_posts( array( 'meta_key' => 'foo', 'meta_value' => '0' ) );
    1044         $this->assertEquals( 1, count ( $posts ) );
    1045         foreach ( $posts as $post ) {
     1422        $q = new WP_Query( array( 'meta_key' => 'foo', 'meta_value' => '0' ) );
     1423        $this->assertEquals( 1, count ( $q->posts ) );
     1424        foreach ( $q->posts as $post ) {
    10461425            $this->assertInstanceOf( 'WP_Post', $post );
    10471426            $this->assertEquals( 'raw', $post->filter );
    10481427        }
    1049         $this->assertEquals( $post_id, $posts[0]->ID );
     1428        $this->assertEquals( $post_id, $q->posts[0]->ID );
    10501429
    10511430        $posts = get_posts( array( 'meta_key' => 'bar', 'meta_value' => '0' ) );
Note: See TracChangeset for help on using the changeset viewer.