Make WordPress Core

Changeset 59766


Ignore:
Timestamp:
02/06/2025 05:02:17 AM (18 months ago)
Author:
peterwilsoncc
Message:

Query: Increase WP_Query cache hits for equivalent arguments.

Introduces normalization a number of arguments passed to WP_Query to increase cache hits for equivalent requests. For example author__in => [ 1, 2 ] and author__in => [ 2, 1 ] will now hit the same cache.

Prior to generating the SQL request and cache key, the following are sorted, made unique and type cast as appropriate.

  • post_type when passed as an array
  • post_status when passed as an array
  • term_querys containing terms
  • cat
  • category__in
  • category__not_in
  • category__and
  • tag_slug__in
  • tag__in
  • tag__not_in
  • tag__and
  • tag_slug__in
  • tag_slug__and
  • post_parent__not_in
  • author
  • author__not_in
  • author__in

The following are sorted for the purposes of generating the cache key and SQL WHERE clause but unmodified for use in the ORDER BY SQL clause:

  • post_name__in
  • post__in
  • post_parent__in

This commit includes changes to unrelated tests, assertions in Tests_Query_ParseQuery::test_parse_query_cat_array_mixed() and WP_Test_REST_Posts_Controller::test_get_items_not_sticky_with_exclude() have been modified to account for the sorting of the items above.

Props thekt12, peterwilsoncc, spacedmonkey, joemcgill, flixos90, mukesh27, pbearne, swissspidy.
Fixes #59516.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-query.php

    r59495 r59766  
    474474
    475475        private $compat_methods = array( 'init_query_flags', 'parse_tax_query' );
     476
     477        /**
     478         * The cache key generated by the query.
     479         *
     480         * The cache key is generated by the method ::generate_cache_key() after the
     481         * query has been normalized.
     482         *
     483         * @var string
     484         */
     485        private $query_cache_key = '';
    476486
    477487        /**
     
    11021112                if ( ! empty( $qv['post_type'] ) ) {
    11031113                        if ( is_array( $qv['post_type'] ) ) {
    1104                                 $qv['post_type'] = array_map( 'sanitize_key', $qv['post_type'] );
     1114                                $qv['post_type'] = array_map( 'sanitize_key', array_unique( $qv['post_type'] ) );
     1115                                sort( $qv['post_type'] );
    11051116                        } else {
    11061117                                $qv['post_type'] = sanitize_key( $qv['post_type'] );
     
    11101121                if ( ! empty( $qv['post_status'] ) ) {
    11111122                        if ( is_array( $qv['post_status'] ) ) {
    1112                                 $qv['post_status'] = array_map( 'sanitize_key', $qv['post_status'] );
     1123                                $qv['post_status'] = array_map( 'sanitize_key', array_unique( $qv['post_status'] ) );
     1124                                sort( $qv['post_status'] );
    11131125                        } else {
    11141126                                $qv['post_status'] = preg_replace( '|[^a-z0-9_,-]|', '', $qv['post_status'] );
     
    11831195                                $term = $q[ $t->query_var ];
    11841196
    1185                                 if ( is_array( $term ) ) {
    1186                                         $term = implode( ',', $term );
    1187                                 }
     1197                                if ( ! is_array( $term ) ) {
     1198                                        $term = explode( ',', $term );
     1199                                        $term = array_map( 'trim', $term );
     1200                                }
     1201                                sort( $term );
     1202                                $term = implode( ',', $term );
    11881203
    11891204                                if ( str_contains( $term, '+' ) ) {
     
    12211236                        $cat_array = preg_split( '/[,\s]+/', urldecode( $q['cat'] ) );
    12221237                        $cat_array = array_map( 'intval', $cat_array );
    1223                         $q['cat']  = implode( ',', $cat_array );
     1238                        sort( $cat_array );
     1239                        $q['cat'] = implode( ',', $cat_array );
    12241240
    12251241                        foreach ( $cat_array as $cat ) {
     
    12631279                if ( ! empty( $q['category__in'] ) ) {
    12641280                        $q['category__in'] = array_map( 'absint', array_unique( (array) $q['category__in'] ) );
    1265                         $tax_query[]       = array(
     1281                        sort( $q['category__in'] );
     1282                        $tax_query[] = array(
    12661283                                'taxonomy'         => 'category',
    12671284                                'terms'            => $q['category__in'],
     
    12731290                if ( ! empty( $q['category__not_in'] ) ) {
    12741291                        $q['category__not_in'] = array_map( 'absint', array_unique( (array) $q['category__not_in'] ) );
     1292                        sort( $q['category__not_in'] );
    12751293                        $tax_query[]           = array(
    12761294                                'taxonomy'         => 'category',
     
    12831301                if ( ! empty( $q['category__and'] ) ) {
    12841302                        $q['category__and'] = array_map( 'absint', array_unique( (array) $q['category__and'] ) );
    1285                         $tax_query[]        = array(
     1303                        sort( $q['category__and'] );
     1304                        $tax_query[] = array(
    12861305                                'taxonomy'         => 'category',
    12871306                                'terms'            => $q['category__and'],
     
    13011320                if ( '' !== $q['tag'] && ! $this->is_singular && $this->query_vars_changed ) {
    13021321                        if ( str_contains( $q['tag'], ',' ) ) {
     1322                                // @todo Handle normalizing `tag` query string.
    13031323                                $tags = preg_split( '/[,\r\n\t ]+/', $q['tag'] );
    13041324                                foreach ( (array) $tags as $tag ) {
    13051325                                        $tag                 = sanitize_term_field( 'slug', $tag, 0, 'post_tag', 'db' );
    13061326                                        $q['tag_slug__in'][] = $tag;
     1327                                        sort( $q['tag_slug__in'] );
    13071328                                }
    13081329                        } elseif ( preg_match( '/[+\r\n\t ]+/', $q['tag'] ) || ! empty( $q['cat'] ) ) {
     
    13151336                                $q['tag']            = sanitize_term_field( 'slug', $q['tag'], 0, 'post_tag', 'db' );
    13161337                                $q['tag_slug__in'][] = $q['tag'];
     1338                                sort( $q['tag_slug__in'] );
    13171339                        }
    13181340                }
     
    13281350                if ( ! empty( $q['tag__in'] ) ) {
    13291351                        $q['tag__in'] = array_map( 'absint', array_unique( (array) $q['tag__in'] ) );
    1330                         $tax_query[]  = array(
     1352                        sort( $q['tag__in'] );
     1353                        $tax_query[] = array(
    13311354                                'taxonomy' => 'post_tag',
    13321355                                'terms'    => $q['tag__in'],
     
    13361359                if ( ! empty( $q['tag__not_in'] ) ) {
    13371360                        $q['tag__not_in'] = array_map( 'absint', array_unique( (array) $q['tag__not_in'] ) );
     1361                        sort( $q['tag__not_in'] );
    13381362                        $tax_query[]      = array(
    13391363                                'taxonomy' => 'post_tag',
     
    13451369                if ( ! empty( $q['tag__and'] ) ) {
    13461370                        $q['tag__and'] = array_map( 'absint', array_unique( (array) $q['tag__and'] ) );
    1347                         $tax_query[]   = array(
     1371                        sort( $q['tag__and'] );
     1372                        $tax_query[] = array(
    13481373                                'taxonomy' => 'post_tag',
    13491374                                'terms'    => $q['tag__and'],
     
    13541379                if ( ! empty( $q['tag_slug__in'] ) ) {
    13551380                        $q['tag_slug__in'] = array_map( 'sanitize_title_for_query', array_unique( (array) $q['tag_slug__in'] ) );
    1356                         $tax_query[]       = array(
     1381                        sort( $q['tag_slug__in'] );
     1382                        $tax_query[] = array(
    13571383                                'taxonomy' => 'post_tag',
    13581384                                'terms'    => $q['tag_slug__in'],
     
    13631389                if ( ! empty( $q['tag_slug__and'] ) ) {
    13641390                        $q['tag_slug__and'] = array_map( 'sanitize_title_for_query', array_unique( (array) $q['tag_slug__and'] ) );
    1365                         $tax_query[]        = array(
     1391                        sort( $q['tag_slug__and'] );
     1392                        $tax_query[] = array(
    13661393                                'taxonomy' => 'post_tag',
    13671394                                'terms'    => $q['tag_slug__and'],
     
    21872214                } elseif ( is_array( $q['post_name__in'] ) && ! empty( $q['post_name__in'] ) ) {
    21882215                        $q['post_name__in'] = array_map( 'sanitize_title_for_query', $q['post_name__in'] );
    2189                         $post_name__in      = "'" . implode( "','", $q['post_name__in'] ) . "'";
    2190                         $where             .= " AND {$wpdb->posts}.post_name IN ($post_name__in)";
     2216                        // Duplicate array before sorting to allow for the orderby clause.
     2217                        $post_name__in_for_where = array_unique( $q['post_name__in'] );
     2218                        sort( $post_name__in_for_where );
     2219                        $post_name__in = "'" . implode( "','", $post_name__in_for_where ) . "'";
     2220                        $where        .= " AND {$wpdb->posts}.post_name IN ($post_name__in)";
    21912221                }
    21922222
     
    22002230                        $where .= " AND {$wpdb->posts}.ID = " . $q['p'];
    22012231                } elseif ( $q['post__in'] ) {
    2202                         $post__in = implode( ',', array_map( 'absint', $q['post__in'] ) );
     2232                        // Duplicate array before sorting to allow for the orderby clause.
     2233                        $post__in_for_where = $q['post__in'];
     2234                        $post__in_for_where = array_unique( array_map( 'absint', $post__in_for_where ) );
     2235                        sort( $post__in_for_where );
     2236                        $post__in = implode( ',', array_map( 'absint', $post__in_for_where ) );
    22032237                        $where   .= " AND {$wpdb->posts}.ID IN ($post__in)";
    22042238                } elseif ( $q['post__not_in'] ) {
     2239                        sort( $q['post__not_in'] );
    22052240                        $post__not_in = implode( ',', array_map( 'absint', $q['post__not_in'] ) );
    22062241                        $where       .= " AND {$wpdb->posts}.ID NOT IN ($post__not_in)";
     
    22102245                        $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_parent = %d ", $q['post_parent'] );
    22112246                } elseif ( $q['post_parent__in'] ) {
    2212                         $post_parent__in = implode( ',', array_map( 'absint', $q['post_parent__in'] ) );
     2247                        // Duplicate array before sorting to allow for the orderby clause.
     2248                        $post_parent__in_for_where = $q['post_parent__in'];
     2249                        $post_parent__in_for_where = array_unique( array_map( 'absint', $post_parent__in_for_where ) );
     2250                        sort( $post_parent__in_for_where );
     2251                        $post_parent__in = implode( ',', array_map( 'absint', $post_parent__in_for_where ) );
    22132252                        $where          .= " AND {$wpdb->posts}.post_parent IN ($post_parent__in)";
    22142253                } elseif ( $q['post_parent__not_in'] ) {
     2254                        sort( $q['post_parent__not_in'] );
    22152255                        $post_parent__not_in = implode( ',', array_map( 'absint', $q['post_parent__not_in'] ) );
    22162256                        $where              .= " AND {$wpdb->posts}.post_parent NOT IN ($post_parent__not_in)";
     
    23422382                        $q['author'] = addslashes_gpc( '' . urldecode( $q['author'] ) );
    23432383                        $authors     = array_unique( array_map( 'intval', preg_split( '/[,\s]+/', $q['author'] ) ) );
     2384                        sort( $authors );
    23442385                        foreach ( $authors as $author ) {
    23452386                                $key         = $author > 0 ? 'author__in' : 'author__not_in';
     
    23502391
    23512392                if ( ! empty( $q['author__not_in'] ) ) {
    2352                         $author__not_in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__not_in'] ) ) );
     2393                        if ( is_array( $q['author__not_in'] ) ) {
     2394                                $q['author__not_in'] = array_unique( array_map( 'absint', $q['author__not_in'] ) );
     2395                                sort( $q['author__not_in'] );
     2396                        }
     2397                        $author__not_in = implode( ',', (array) $q['author__not_in'] );
    23532398                        $where         .= " AND {$wpdb->posts}.post_author NOT IN ($author__not_in) ";
    23542399                } elseif ( ! empty( $q['author__in'] ) ) {
     2400                        if ( is_array( $q['author__in'] ) ) {
     2401                                $q['author__in'] = array_unique( array_map( 'absint', $q['author__in'] ) );
     2402                                sort( $q['author__in'] );
     2403                        }
    23552404                        $author__in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__in'] ) ) );
    23562405                        $where     .= " AND {$wpdb->posts}.post_author IN ($author__in) ";
     
    25892638                                $q_status = explode( ',', $q_status );
    25902639                        }
     2640                        sort( $q_status );
    25912641                        $r_status = array();
    25922642                        $p_status = array();
     
    49034953                sort( $args['post_type'] );
    49044954
     4955                /*
     4956                 * Sort arrays that can be used for ordering prior to cache key generation.
     4957                 *
     4958                 * These arrays are sorted in the query generator for the purposes of the
     4959                 * WHERE clause but the arguments are not modified as they can be used for
     4960                 * the orderby clase.
     4961                 *
     4962                 * Their use in the orderby clause will generate a different SQL query so
     4963                 * they can be sorted for the cache key generation.
     4964                 */
     4965                $sortable_arrays_with_int_values = array(
     4966                        'post__in',
     4967                        'post_parent__in',
     4968                );
     4969                foreach ( $sortable_arrays_with_int_values as $key ) {
     4970                        if ( isset( $args[ $key ] ) && is_array( $args[ $key ] ) ) {
     4971                                $args[ $key ] = array_unique( array_map( 'absint', $args[ $key ] ) );
     4972                                sort( $args[ $key ] );
     4973                        }
     4974                }
     4975
     4976                // Sort and unique the 'post_name__in' for cache key generation.
     4977                if ( isset( $args['post_name__in'] ) && is_array( $args['post_name__in'] ) ) {
     4978                        $args['post_name__in'] = array_unique( $args['post_name__in'] );
     4979                        sort( $args['post_name__in'] );
     4980                }
     4981
    49054982                if ( isset( $args['post_status'] ) ) {
    49064983                        $args['post_status'] = (array) $args['post_status'];
     
    49435020                }
    49445021
    4945                 return "wp_query:$key:$last_changed";
     5022                $this->query_cache_key = "wp_query:$key:$last_changed";
     5023                return $this->query_cache_key;
    49465024        }
    49475025
  • trunk/tests/phpunit/tests/query/cacheResults.php

    r58122 r59766  
    202202
    203203        /**
    204          * @ticket 59442
     204         * @ticket 59516
    205205         *
    206206         * @covers WP_Query::generate_cache_key
    207          *
    208          * @dataProvider data_query_cache_duplicate
    209          */
    210         public function test_generate_cache_key_normalize( $query_vars1, $query_vars2 ) {
     207         */
     208        public function test_post_in_order_by_clauses_are_not_normalized() {
    211209                global $wpdb;
     210
     211                $post_ids = self::$posts;
     212
     213                $query_vars1 = array(
     214                        'post__in' => $post_ids,
     215                        'orderby'  => 'post__in',
     216                );
     217                $query_vars2 = array(
     218                        'post__in' => array_reverse( $post_ids ),
     219                        'orderby'  => 'post__in',
     220                );
    212221
    213222                $fields   = "{$wpdb->posts}.ID";
     
    218227                $request2 = str_replace( $fields, "{$wpdb->posts}.*", $query2->request );
    219228
    220                 $reflection = new ReflectionMethod( $query1, 'generate_cache_key' );
    221                 $reflection->setAccessible( true );
     229                $reflection_q1 = new ReflectionProperty( $query1, 'query_cache_key' );
     230                $reflection_q1->setAccessible( true );
     231
     232                $reflection_q2 = new ReflectionProperty( $query2, 'query_cache_key' );
     233                $reflection_q2->setAccessible( true );
     234
     235                $this->assertNotSame( $request1, $request2, 'Queries should not match' );
     236
     237                $cache_key_1 = $reflection_q1->getValue( $query1 );
     238                $cache_key_2 = $reflection_q2->getValue( $query2 );
     239
     240                $this->assertNotSame( $cache_key_1, $cache_key_2, 'Cache key should differ.' );
     241                $this->assertNotEmpty( $cache_key_1, 'Cache key for query one should not be empty.' );
     242                $this->assertNotEmpty( $cache_key_2, 'Cache key for query two should not be empty.' );
     243
     244                // Test the posts are returned different orders.
     245                $this->assertNotSame( wp_list_pluck( $query1->posts, 'ID' ), wp_list_pluck( $query2->posts, 'ID' ), 'Query one posts should not match the order of query two posts.' );
     246                // Test the posts are the same sets.
     247                $this->assertSameSets( wp_list_pluck( $query1->posts, 'ID' ), wp_list_pluck( $query2->posts, 'ID' ), 'Query one posts should match the set of query two posts.' );
     248        }
     249
     250        /**
     251         * @ticket 59516
     252         *
     253         * @covers WP_Query::generate_cache_key
     254         */
     255        public function test_post_parent_in_order_by_clauses_are_not_normalized() {
     256                global $wpdb;
     257
     258                $parent_pages = self::$pages;
     259                $post_names   = array( 'doctor-dillamond', 'elphaba', 'fiyero', 'glinda', 'the-wizard-of-oz' );
     260                $child_pages  = array();
     261                foreach ( $parent_pages as $key => $parent_page ) {
     262                        $child_pages[] = self::factory()->post->create(
     263                                array(
     264                                        'post_parent' => $parent_page,
     265                                        'post_type'   => 'page',
     266                                        'post_name'   => $post_names[ $key ],
     267                                )
     268                        );
     269                }
     270
     271                $query_vars1 = array(
     272                        'post_parent__in' => $parent_pages,
     273                        'post_type'       => 'page',
     274                        'orderby'         => 'post_parent__in',
     275                );
     276
     277                $query_vars2 = array(
     278                        'post_parent__in' => array_reverse( $parent_pages ),
     279                        'post_type'       => 'page',
     280                        'orderby'         => 'post_parent__in',
     281                );
     282
     283                $fields   = "{$wpdb->posts}.ID";
     284                $query1   = new WP_Query( $query_vars1 );
     285                $request1 = str_replace( $fields, "{$wpdb->posts}.*", $query1->request );
     286
     287                $query2   = new WP_Query( $query_vars2 );
     288                $request2 = str_replace( $fields, "{$wpdb->posts}.*", $query2->request );
     289
     290                $reflection_q1 = new ReflectionProperty( $query1, 'query_cache_key' );
     291                $reflection_q1->setAccessible( true );
     292
     293                $reflection_q2 = new ReflectionProperty( $query2, 'query_cache_key' );
     294                $reflection_q2->setAccessible( true );
     295
     296                $this->assertNotSame( $request1, $request2, 'Queries should not match' );
     297
     298                $cache_key_1 = $reflection_q1->getValue( $query1 );
     299                $cache_key_2 = $reflection_q2->getValue( $query2 );
     300
     301                $this->assertNotSame( $cache_key_1, $cache_key_2, 'Cache key should differ.' );
     302                $this->assertNotEmpty( $cache_key_1, 'Cache key for query one should not be empty.' );
     303                $this->assertNotEmpty( $cache_key_2, 'Cache key for query two should not be empty.' );
     304
     305                // Test the posts are returned in the correct order.
     306                $this->assertSame( array( 'doctor-dillamond', 'elphaba', 'fiyero', 'glinda', 'the-wizard-of-oz' ), wp_list_pluck( $query1->posts, 'post_name' ), 'Query one posts should be in alphabetical order' );
     307                $this->assertSame( array( 'the-wizard-of-oz', 'glinda', 'fiyero', 'elphaba', 'doctor-dillamond' ), wp_list_pluck( $query2->posts, 'post_name' ), 'Query two posts should be in reverse alphabetical order.' );
     308                // Test the posts are the same sets.
     309                $this->assertSameSets( wp_list_pluck( $query1->posts, 'ID' ), wp_list_pluck( $query2->posts, 'ID' ), 'Query one posts should match the set of query two posts.' );
     310        }
     311
     312        /**
     313         * @ticket 59516
     314         *
     315         * @covers WP_Query::generate_cache_key
     316         */
     317        public function test_post_name_in_order_by_clauses_are_not_normalized() {
     318                global $wpdb;
     319                $post_names = array( 'doctor-dillamond', 'elphaba', 'glinda', 'the-wizard-of-oz' );
     320                $posts      = array();
     321
     322                foreach ( $post_names as $post_name ) {
     323                        $posts[] = self::factory()->post->create(
     324                                array(
     325                                        'post_name' => $post_name,
     326                                )
     327                        );
     328                }
     329
     330                $query_vars1 = array(
     331                        'post_name__in' => $post_names,
     332                        'orderby'       => 'post_name__in',
     333                );
     334
     335                $query_vars2 = array(
     336                        'post_name__in' => array_reverse( $post_names ),
     337                        'orderby'       => 'post_name__in',
     338                );
     339
     340                $fields   = "{$wpdb->posts}.ID";
     341                $query1   = new WP_Query( $query_vars1 );
     342                $request1 = str_replace( $fields, "{$wpdb->posts}.*", $query1->request );
     343
     344                $query2   = new WP_Query( $query_vars2 );
     345                $request2 = str_replace( $fields, "{$wpdb->posts}.*", $query2->request );
     346
     347                $reflection_q1 = new ReflectionProperty( $query1, 'query_cache_key' );
     348                $reflection_q1->setAccessible( true );
     349
     350                $reflection_q2 = new ReflectionProperty( $query2, 'query_cache_key' );
     351                $reflection_q2->setAccessible( true );
     352
     353                $this->assertNotSame( $request1, $request2, 'Queries should not match' );
     354
     355                $cache_key_1 = $reflection_q1->getValue( $query1 );
     356                $cache_key_2 = $reflection_q2->getValue( $query2 );
     357
     358                $this->assertNotSame( $cache_key_1, $cache_key_2, 'Cache key should differ.' );
     359                $this->assertNotEmpty( $cache_key_1, 'Cache key for query one should not be empty.' );
     360                $this->assertNotEmpty( $cache_key_2, 'Cache key for query two should not be empty.' );
     361
     362                // Test the posts are returned in the correct order.
     363                $this->assertSame( array( 'doctor-dillamond', 'elphaba', 'glinda', 'the-wizard-of-oz' ), wp_list_pluck( $query1->posts, 'post_name' ), 'Query one posts should be in alphabetical order' );
     364                $this->assertSame( array( 'the-wizard-of-oz', 'glinda', 'elphaba', 'doctor-dillamond' ), wp_list_pluck( $query2->posts, 'post_name' ), 'Query two posts should be in reverse alphabetical order.' );
     365                // Test the posts are the same sets.
     366                $this->assertSameSets( wp_list_pluck( $query1->posts, 'ID' ), wp_list_pluck( $query2->posts, 'ID' ), 'Query one posts should match the set of query two posts.' );
     367        }
     368
     369        /**
     370         * @ticket 59442
     371         * @ticket 59516
     372         *
     373         * @covers WP_Query::generate_cache_key
     374         *
     375         * @dataProvider data_query_cache_duplicate
     376         */
     377        public function test_generate_cache_key_normalize( $query_vars1, $query_vars2 ) {
     378                global $wpdb;
     379
     380                $fields   = "{$wpdb->posts}.ID";
     381                $query1   = new WP_Query( $query_vars1 );
     382                $request1 = str_replace( $fields, "{$wpdb->posts}.*", $query1->request );
     383
     384                $query2   = new WP_Query( $query_vars2 );
     385                $request2 = str_replace( $fields, "{$wpdb->posts}.*", $query2->request );
     386
     387                $reflection_q1 = new ReflectionProperty( $query1, 'query_cache_key' );
     388                $reflection_q1->setAccessible( true );
     389
     390                $reflection_q2 = new ReflectionProperty( $query2, 'query_cache_key' );
     391                $reflection_q2->setAccessible( true );
    222392
    223393                $this->assertSame( $request1, $request2, 'Queries should match' );
    224394
    225                 $cache_key_1 = $reflection->invoke( $query1, $query_vars1, $request1 );
    226                 $cache_key_2 = $reflection->invoke( $query1, $query_vars2, $request2 );
    227 
    228                 $this->assertSame( $cache_key_1, $cache_key_2, 'Cache key differs the same paramters.' );
     395                $cache_key_1 = $reflection_q1->getValue( $query1 );
     396                $cache_key_2 = $reflection_q2->getValue( $query2 );
     397
     398                $this->assertSame( $cache_key_1, $cache_key_2, 'Cache key differs the same effective parameters.' );
     399                $this->assertNotEmpty( $cache_key_1, 'Cache key for query one should not be empty.' );
     400                $this->assertNotEmpty( $cache_key_2, 'Cache key for query two should not be empty.' );
    229401        }
    230402
     
    281453        public function data_query_cache_duplicate() {
    282454                return array(
    283                         'post type empty'           => array(
     455                        'post type empty'                              => array(
    284456                                'query_vars1' => array( 'post_type' => '' ),
    285457                                'query_vars2' => array( 'post_type' => 'post' ),
    286458                        ),
    287                         'post type array'           => array(
     459                        'post type array'                              => array(
    288460                                'query_vars1' => array( 'post_type' => array( 'page' ) ),
    289461                                'query_vars2' => array( 'post_type' => 'page' ),
    290462                        ),
    291                         'orderby empty'             => array(
     463                        'orderby empty'                                => array(
    292464                                'query_vars1' => array( 'orderby' => null ),
    293465                                'query_vars2' => array( 'orderby' => 'date' ),
    294466                        ),
    295                         'different order parameter' => array(
     467                        'different order parameter'                    => array(
    296468                                'query_vars1' => array(
    297469                                        'post_type'      => 'post',
     
    303475                                ),
    304476                        ),
    305                         'same args'                 => array(
     477                        'same args'                                    => array(
    306478                                'query_vars1' => array( 'post_type' => 'post' ),
    307479                                'query_vars2' => array( 'post_type' => 'post' ),
    308480                        ),
    309                         'same args any'             => array(
     481                        'same args any'                                => array(
    310482                                'query_vars1' => array( 'post_type' => 'any' ),
    311483                                'query_vars2' => array( 'post_type' => 'any' ),
    312484                        ),
    313                         'any and post types'        => array(
     485                        'any and post types'                           => array(
    314486                                'query_vars1' => array( 'post_type' => 'any' ),
    315487                                'query_vars2' => array( 'post_type' => array( 'post', 'page', 'attachment' ) ),
    316488                        ),
    317                         'different order post type' => array(
     489                        'different order post type'                    => array(
    318490                                'query_vars1' => array( 'post_type' => array( 'post', 'page' ) ),
    319491                                'query_vars2' => array( 'post_type' => array( 'page', 'post' ) ),
    320492                        ),
    321                         'post status array'         => array(
     493                        'non-unique post type'                         => array(
     494                                'query_vars1' => array( 'post_type' => array( 'post', 'page' ) ),
     495                                'query_vars2' => array( 'post_type' => array( 'page', 'post', 'page' ) ),
     496                        ),
     497                        'post status array'                            => array(
    322498                                'query_vars1' => array( 'post_status' => 'publish' ),
    323499                                'query_vars2' => array( 'post_status' => array( 'publish' ) ),
    324500                        ),
    325                         'post status order'         => array(
     501                        'post status order'                            => array(
    326502                                'query_vars1' => array( 'post_status' => array( 'draft', 'publish' ) ),
    327503                                'query_vars2' => array( 'post_status' => array( 'publish', 'draft' ) ),
    328504                        ),
    329                         'cache parameters'          => array(
     505                        'non-unique post status'                       => array(
     506                                'query_vars1' => array( 'post_status' => array( 'draft', 'publish' ) ),
     507                                'query_vars2' => array( 'post_status' => array( 'draft', 'publish', 'draft' ) ),
     508                        ),
     509                        'post id int vs string'                        => array(
     510                                'query_vars1' => array( 'p' => '1' ),
     511                                'query_vars2' => array( 'p' => 1 ),
     512                        ),
     513                        'page id int vs string'                        => array(
     514                                'query_vars1' => array( 'page_id' => '2' ),
     515                                'query_vars2' => array( 'page_id' => 2 ),
     516                        ),
     517                        'attachment id int vs string'                  => array(
     518                                'query_vars1' => array( 'attachment_id' => '3' ),
     519                                'query_vars2' => array( 'attachment_id' => 3 ),
     520                        ),
     521                        'date and time values int vs string'           => array(
     522                                'query_vars1' => array(
     523                                        'year'     => '2013',
     524                                        'monthnum' => '12',
     525                                        'day'      => '12',
     526                                        'hour'     => '12',
     527                                        'minute'   => '12',
     528                                        'second'   => '12',
     529                                ),
     530                                'query_vars2' => array(
     531                                        'year'     => 2013,
     532                                        'monthnum' => 12,
     533                                        'day'      => 12,
     534                                        'hour'     => 12,
     535                                        'minute'   => 12,
     536                                        'second'   => 12,
     537                                ),
     538                        ),
     539                        'offset value int vs string'                   => array(
     540                                'query_vars1' => array( 'offset' => '5' ),
     541                                'query_vars2' => array( 'offset' => 5 ),
     542                        ),
     543                        'posts per page value int vs string'           => array(
     544                                'query_vars1' => array( 'posts_per_page' => '5' ),
     545                                'query_vars2' => array( 'posts_per_page' => 5 ),
     546                        ),
     547                        'paged value int vs string'                    => array(
     548                                'query_vars1' => array( 'paged' => '2' ),
     549                                'query_vars2' => array( 'paged' => 2 ),
     550                        ),
     551                        'menu_order value int vs string'               => array(
     552                                'query_vars1' => array( 'menu_order' => '2' ),
     553                                'query_vars2' => array( 'menu_order' => 2 ),
     554                        ),
     555                        'post__in different order'                     => array(
     556                                'query_vars1' => array( 'post__in' => array( 1, 2, 3, 4, 5 ) ),
     557                                'query_vars2' => array( 'post__in' => array( 5, 4, 3, 2, 1 ) ),
     558                        ),
     559                        'post__in non-unique'                          => array(
     560                                'query_vars1' => array( 'post__in' => array( 1, 2, 3, 4, 5 ) ),
     561                                'query_vars2' => array( 'post__in' => array( 1, 2, 3, 4, 5, 1, 2, 3 ) ),
     562                        ),
     563                        'post_parent__in different order'              => array(
     564                                'query_vars1' => array( 'post_parent__in' => array( 1, 2, 3, 4, 5 ) ),
     565                                'query_vars2' => array( 'post_parent__in' => array( 5, 4, 3, 2, 1 ) ),
     566                        ),
     567                        'post_parent__in non-unique'                   => array(
     568                                'query_vars1' => array( 'post_parent__in' => array( 1, 2, 3, 4, 5 ) ),
     569                                'query_vars2' => array( 'post_parent__in' => array( 1, 2, 3, 4, 5, 1, 2, 3 ) ),
     570                        ),
     571                        'post_name__in different order'                => array(
     572                                'query_vars1' => array( 'post_name__in' => array( 'elphaba', 'glinda', 'the-wizard-of-oz', 'doctor-dillamond' ) ),
     573                                'query_vars2' => array( 'post_name__in' => array( 'doctor-dillamond', 'elphaba', 'the-wizard-of-oz', 'glinda' ) ),
     574                        ),
     575                        'post_name__in non-unique'                     => array(
     576                                'query_vars1' => array( 'post_name__in' => array( 'elphaba', 'glinda', 'the-wizard-of-oz', 'doctor-dillamond' ) ),
     577                                'query_vars2' => array( 'post_name__in' => array( 'elphaba', 'glinda', 'elphaba', 'glinda', 'the-wizard-of-oz', 'doctor-dillamond' ) ),
     578                        ),
     579                        'cat different order (array)'                  => array(
     580                                'query_vars_1' => array( 'cat' => array( '1', '2' ) ),
     581                                'query_vars_2' => array( 'cat' => array( '2', '1' ) ),
     582                        ),
     583                        'cat different order (string)'                 => array(
     584                                'query_vars_1' => array( 'cat' => '2,1' ),
     585                                'query_vars_2' => array( 'cat' => '1,2' ),
     586                        ),
     587                        'cat queries int vs string'                    => array(
     588                                'query_vars_1' => array( 'cat' => '2' ),
     589                                'query_vars_2' => array( 'cat' => 2 ),
     590                        ),
     591                        'category__in queries different order (array)' => array(
     592                                'query_vars_1' => array( 'category__in' => array( '1', '2' ) ),
     593                                'query_vars_2' => array( 'category__in' => array( '2', '1' ) ),
     594                        ),
     595                        'category__in queries with non-unique array'   => array(
     596                                'query_vars_1' => array( 'category__in' => array( '1', '1' ) ),
     597                                'query_vars_2' => array( 'category__in' => array( '1' ) ),
     598                        ),
     599                        'category__in queries string vs array (array)' => array(
     600                                'query_vars_1' => array( 'category__in' => array( '1' ) ),
     601                                'query_vars_2' => array( 'category__in' => array( 1 ) ),
     602                        ),
     603                        'category__not_in different order (array)'     => array(
     604                                'query_vars_1' => array( 'category__not_in' => array( '1', '2' ) ),
     605                                'query_vars_2' => array( 'category__not_in' => array( '2', '1' ) ),
     606                        ),
     607                        'category__not_in with non-unique array'       => array(
     608                                'query_vars_1' => array( 'category__not_in' => array( '1', '1' ) ),
     609                                'query_vars_2' => array( 'category__not_in' => array( '1' ) ),
     610                        ),
     611                        'category__not_in queries string vs array (array)' => array(
     612                                'query_vars_1' => array( 'category__not_in' => array( '1' ) ),
     613                                'query_vars_2' => array( 'category__not_in' => array( 1 ) ),
     614                        ),
     615                        'category__and queries width different order (array)' => array(
     616                                'query_vars_1' => array( 'category__and' => array( '1', '2' ) ),
     617                                'query_vars_2' => array( 'category__and' => array( '2', '1' ) ),
     618                        ),
     619                        'category__and with non-unique array'          => array(
     620                                'query_vars_1' => array( 'category__and' => array( '1', '1', '2' ) ),
     621                                'query_vars_2' => array( 'category__and' => array( '1', '2' ) ),
     622                        ),
     623                        'category__and queries string vs array (array)' => array(
     624                                'query_vars_1' => array( 'category__and' => array( '1', '2' ) ),
     625                                'query_vars_2' => array( 'category__and' => array( 1, 2 ) ),
     626                        ),
     627                        'author queries different order (string)'      => array(
     628                                'query_vars_1' => array( 'author' => '1,2' ),
     629                                'query_vars_2' => array( 'author' => '2,1' ),
     630                        ),
     631                        'author with non-unique string'                => array(
     632                                'query_vars_1' => array( 'author' => '1,1' ),
     633                                'query_vars_2' => array( 'author' => '1' ),
     634                        ),
     635                        'author queries int vs string (string)'        => array(
     636                                'query_vars_1' => array( 'author' => 1 ),
     637                                'query_vars_2' => array( 'author' => '1' ),
     638                        ),
     639                        'author queries int vs string (array)'         => array(
     640                                'query_vars_1' => array( 'author' => array( 1 ) ),
     641                                'query_vars_2' => array( 'author' => array( '1' ) ),
     642                        ),
     643                        'author__in different order'                   => array(
     644                                'query_vars_1' => array( 'author__in' => array( 1, 2 ) ),
     645                                'query_vars_2' => array( 'author__in' => array( 2, 1 ) ),
     646                        ),
     647                        'author__in with non-unique array'             => array(
     648                                'query_vars_1' => array( 'author__in' => array( 1, 1, 2 ) ),
     649                                'query_vars_2' => array( 'author__in' => array( 1, 2 ) ),
     650                        ),
     651                        'author__in queries int vs string (array)'     => array(
     652                                'query_vars_1' => array( 'author__in' => array( 1 ) ),
     653                                'query_vars_2' => array( 'author__in' => array( '1' ) ),
     654                        ),
     655                        'author__not_in different order (array)'       => array(
     656                                'query_vars_1' => array( 'author__not_in' => array( 1, 2 ) ),
     657                                'query_vars_2' => array( 'author__not_in' => array( 2, 1 ) ),
     658                        ),
     659                        'author__not_in queries int vs string (array)' => array(
     660                                'query_vars_1' => array( 'author__not_in' => array( 1 ) ),
     661                                'query_vars_2' => array( 'author__not_in' => array( '1' ) ),
     662                        ),
     663                        'tag_slug__in order'                           => array(
     664                                'query_vars_1' => array( 'tag_slug__in' => array( 'foo', 'bar' ) ),
     665                                'query_vars_2' => array( 'tag_slug__in' => array( 'bar', 'foo' ) ),
     666                        ),
     667                        'tag_slug__in non-unique vs unique'            => array(
     668                                'query_vars_1' => array( 'tag_slug__in' => array( 'foo', 'bar', 'bar' ) ),
     669                                'query_vars_2' => array( 'tag_slug__in' => array( 'foo', 'bar' ) ),
     670                        ),
     671                        'tag_slug__and order'                          => array(
     672                                'query_vars_1' => array( 'tag_slug__and' => array( 'foo', 'bar' ) ),
     673                                'query_vars_2' => array( 'tag_slug__and' => array( 'bar', 'foo' ) ),
     674                        ),
     675                        'tag_slug__and non-unique'                     => array(
     676                                'query_vars_1' => array( 'tag_slug__and' => array( 'foo', 'bar', 'foo' ) ),
     677                                'query_vars_2' => array( 'tag_slug__and' => array( 'bar', 'foo' ) ),
     678                        ),
     679                        'tag__in queries different order (array)'      => array(
     680                                'query_vars_1' => array( 'tag__in' => array( 1, 2 ) ),
     681                                'query_vars_2' => array( 'tag__in' => array( 2, 1 ) ),
     682                        ),
     683                        'tag__in queries non-unique array'             => array(
     684                                'query_vars_1' => array( 'tag__in' => array( 1, 2, 1 ) ),
     685                                'query_vars_2' => array( 'tag__in' => array( 2, 1 ) ),
     686                        ),
     687                        'tag__in queries int vs string'                => array(
     688                                'query_vars_1' => array( 'tag__in' => array( 2, 1 ) ),
     689                                'query_vars_2' => array( 'tag__in' => array( '2', '1' ) ),
     690                        ),
     691                        'tag__and queries different order (array)'     => array(
     692                                'query_vars_1' => array( 'tag__and' => array( 1, 2 ) ),
     693                                'query_vars_2' => array( 'tag__and' => array( 2, 1 ) ),
     694                        ),
     695                        'tag__and queries non-unique array'            => array(
     696                                'query_vars_1' => array( 'tag__and' => array( 1, 2, 2 ) ),
     697                                'query_vars_2' => array( 'tag__and' => array( 2, 1 ) ),
     698                        ),
     699                        'tag__not_in queries different order (array)'  => array(
     700                                'query_vars_1' => array( 'tag__not_in' => array( 1, 2 ) ),
     701                                'query_vars_2' => array( 'tag__not_in' => array( 2, 1 ) ),
     702                        ),
     703                        'tag__not_in queries non-unique array'         => array(
     704                                'query_vars_1' => array( 'tag__not_in' => array( 1, 2, 2 ) ),
     705                                'query_vars_2' => array( 'tag__not_in' => array( 1, 2 ) ),
     706                        ),
     707                        'tag__not_in queries int vs string (array)'    => array(
     708                                'query_vars_1' => array( 'tag__not_in' => array( '1' ) ),
     709                                'query_vars_2' => array( 'tag__not_in' => array( 1 ) ),
     710                        ),
     711                        'cache parameters'                             => array(
    330712                                'query_vars1' => array(
    331713                                        'update_post_meta_cache' => true,
  • trunk/tests/phpunit/tests/query/parseQuery.php

    r53891 r59766  
    152152                );
    153153
    154                 $this->assertSame( '1,-1', $q->query_vars['cat'] );
     154                $this->assertSame( '-1,1', $q->query_vars['cat'] );
    155155        }
    156156
  • trunk/tests/phpunit/tests/rest-api/rest-posts-controller.php

    r59630 r59766  
    15751575                $this->assertNotContains( $id3, $ids );
    15761576
    1577                 $this->assertPostsWhere( " AND {posts}.ID NOT IN ($id3,$id2) AND {posts}.post_type = 'post' AND (({posts}.post_status = 'publish'))" );
     1577                $this->assertPostsWhere( " AND {posts}.ID NOT IN ($id2,$id3) AND {posts}.post_type = 'post' AND (({posts}.post_status = 'publish'))" );
    15781578        }
    15791579
Note: See TracChangeset for help on using the changeset viewer.