mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2025-10-16 12:05:38 +00:00
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. git-svn-id: https://develop.svn.wordpress.org/trunk@25255 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
16ef2c2e36
commit
83d1992d34
@ -603,6 +603,30 @@ function get_meta_sql( $meta_query, $type, $primary_table, $primary_id_column, $
|
||||
return $meta_query_obj->get_sql( $type, $primary_table, $primary_id_column, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a meta type, return the appropriate alias if applicable
|
||||
*
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @see WP_Meta_Query
|
||||
*
|
||||
* @param string $type MySQL type to cast meta_value
|
||||
* @return string MySQL type
|
||||
*/
|
||||
function get_meta_type( $type = '' ) {
|
||||
if ( empty( $type ) )
|
||||
return 'CHAR';
|
||||
|
||||
$meta_type = strtoupper( $type );
|
||||
|
||||
if ( ! in_array( $meta_type, array( 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED', 'NUMERIC' ) ) )
|
||||
return 'CHAR';
|
||||
|
||||
if ( 'NUMERIC' == $meta_type )
|
||||
$meta_type = 'SIGNED';
|
||||
|
||||
return $meta_type;
|
||||
}
|
||||
/**
|
||||
* Container class for a multiple metadata query
|
||||
*
|
||||
@ -744,12 +768,7 @@ class WP_Meta_Query {
|
||||
|
||||
foreach ( $queries as $k => $q ) {
|
||||
$meta_key = isset( $q['key'] ) ? trim( $q['key'] ) : '';
|
||||
$meta_type = isset( $q['type'] ) ? strtoupper( $q['type'] ) : 'CHAR';
|
||||
|
||||
if ( 'NUMERIC' == $meta_type )
|
||||
$meta_type = 'SIGNED';
|
||||
elseif ( ! in_array( $meta_type, array( 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED' ) ) )
|
||||
$meta_type = 'CHAR';
|
||||
$meta_type = get_meta_type( isset( $q['type'] ) ? $q['type'] : '' );
|
||||
|
||||
$meta_value = isset( $q['value'] ) ? $q['value'] : null;
|
||||
|
||||
|
||||
@ -2420,7 +2420,12 @@ class WP_Query {
|
||||
break;
|
||||
case $q['meta_key']:
|
||||
case 'meta_value':
|
||||
$orderby = "$wpdb->postmeta.meta_value";
|
||||
if ( isset( $q['meta_type'] ) ) {
|
||||
$meta_type = get_meta_type( $q['meta_type'] );
|
||||
$orderby = "CAST($wpdb->postmeta.meta_value AS {$meta_type})";
|
||||
} else {
|
||||
$orderby = "$wpdb->postmeta.meta_value";
|
||||
}
|
||||
break;
|
||||
case 'meta_value_num':
|
||||
$orderby = "$wpdb->postmeta.meta_value+0";
|
||||
|
||||
@ -150,4 +150,25 @@ class Tests_Meta extends WP_UnitTestCase {
|
||||
$this->assertInternalType( 'int', update_metadata( 'user', $this->author->ID, $key, $value2 ) );
|
||||
$this->assertEquals( $expected2, get_metadata( 'user', $this->author->ID, $key, true ) );
|
||||
}
|
||||
|
||||
function test_meta_type_cast() {
|
||||
$post_id1 = $this->factory->post->create();
|
||||
add_post_meta( $post_id1, 'num_as_longtext', 123 );
|
||||
$post_id2 = $this->factory->post->create();
|
||||
add_post_meta( $post_id2, 'num_as_longtext', 99 );
|
||||
|
||||
$posts = new WP_Query( array(
|
||||
'fields' => 'ids',
|
||||
'post_type' => 'any',
|
||||
'meta_key' => 'num_as_longtext',
|
||||
'meta_value' => '0',
|
||||
'meta_compare' => '>',
|
||||
'meta_type' => 'UNSIGNED',
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC'
|
||||
) );
|
||||
|
||||
$this->assertEquals( array( $post_id2, $post_id1 ), $posts->posts );
|
||||
$this->assertEquals( 2, substr_count( $posts->request, 'CAST(' ) );
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user