WordPress.org

Make WordPress Core

Changeset 25255


Ignore:
Timestamp:
09/05/13 16:56:36 (4 years ago)
Author:
wonderboymusic
Message:

When meta_type is passed with orderby => meta_value, orderby must also use CAST() to avoid scenarios like: SELECTing by UNSIGNED and then ordering by CHAR. Adds unit test.

Fixes #21621.

Location:
trunk
Files:
3 edited

Legend:

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

    r25076 r25255  
    604604} 
    605605 
     606/** 
     607 * Given a meta type, return the appropriate alias if applicable 
     608 * 
     609 * @since 3.7.0 
     610 * 
     611 * @see WP_Meta_Query 
     612 * 
     613 * @param string $type MySQL type to cast meta_value 
     614 * @return string MySQL type 
     615 */ 
     616function get_meta_type( $type = '' ) { 
     617    if ( empty( $type ) ) 
     618        return 'CHAR'; 
     619 
     620    $meta_type = strtoupper( $type ); 
     621 
     622    if ( ! in_array( $meta_type, array( 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED', 'NUMERIC' ) ) ) 
     623        return 'CHAR'; 
     624 
     625    if ( 'NUMERIC' == $meta_type ) 
     626        $meta_type = 'SIGNED'; 
     627 
     628    return $meta_type; 
     629} 
    606630/** 
    607631 * Container class for a multiple metadata query 
     
    745769        foreach ( $queries as $k => $q ) { 
    746770            $meta_key = isset( $q['key'] ) ? trim( $q['key'] ) : ''; 
    747             $meta_type = isset( $q['type'] ) ? strtoupper( $q['type'] ) : 'CHAR'; 
    748  
    749             if ( 'NUMERIC' == $meta_type ) 
    750                 $meta_type = 'SIGNED'; 
    751             elseif ( ! in_array( $meta_type, array( 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED' ) ) ) 
    752                 $meta_type = 'CHAR'; 
     771            $meta_type = get_meta_type( isset( $q['type'] ) ? $q['type'] : '' ); 
    753772 
    754773            $meta_value = isset( $q['value'] ) ? $q['value'] : null; 
  • trunk/src/wp-includes/query.php

    r25248 r25255  
    24212421                    case $q['meta_key']: 
    24222422                    case 'meta_value': 
    2423                         $orderby = "$wpdb->postmeta.meta_value"; 
     2423                        if ( isset( $q['meta_type'] ) ) { 
     2424                            $meta_type = get_meta_type( $q['meta_type'] ); 
     2425                            $orderby = "CAST($wpdb->postmeta.meta_value AS {$meta_type})"; 
     2426                        } else { 
     2427                            $orderby = "$wpdb->postmeta.meta_value"; 
     2428                        }    
    24242429                        break; 
    24252430                    case 'meta_value_num': 
  • trunk/tests/phpunit/tests/meta.php

    r25254 r25255  
    151151        $this->assertEquals( $expected2, get_metadata( 'user', $this->author->ID, $key, true ) ); 
    152152    } 
     153 
     154    function test_meta_type_cast() { 
     155        $post_id1 = $this->factory->post->create(); 
     156        add_post_meta( $post_id1, 'num_as_longtext', 123 ); 
     157        $post_id2 = $this->factory->post->create(); 
     158        add_post_meta( $post_id2, 'num_as_longtext', 99 ); 
     159 
     160        $posts = new WP_Query( array( 
     161            'fields' => 'ids', 
     162            'post_type' => 'any', 
     163            'meta_key' => 'num_as_longtext', 
     164            'meta_value' => '0', 
     165            'meta_compare' => '>', 
     166            'meta_type' => 'UNSIGNED', 
     167            'orderby' => 'meta_value', 
     168            'order' => 'ASC' 
     169        ) ); 
     170 
     171        $this->assertEquals( array( $post_id2, $post_id1 ), $posts->posts ); 
     172        $this->assertEquals( 2, substr_count( $posts->request, 'CAST(' ) ); 
     173    } 
    153174} 
Note: See TracChangeset for help on using the changeset viewer.