diff --git tests/phpunit/tests/meta/query.php tests/phpunit/tests/meta/query.php
index fdd7693..6da583f 100644
--- tests/phpunit/tests/meta/query.php
+++ tests/phpunit/tests/meta/query.php
@@ -2,17 +2,24 @@
 /**
  * Test WP_Meta_Query, in wp-includes/meta.php
  *
+ * See tests/post/query.php for tests that involve post queries.
+ *
  * @group meta
  */
 class Tests_Meta_Query extends WP_UnitTestCase {
 
-	function test_default_relation() {
+	public function test_empty_meta_query_param() {
+		$query = new WP_Meta_Query();
+		$this->assertSame( null, $query->relation );
+	}
+
+	public function test_default_relation() {
 		$query = new WP_Meta_Query( array( array( 'key' => 'abc' ) ) );
 
 		$this->assertEquals( 'AND', $query->relation );
 	}
 
-	function test_set_relation() {
+	public function test_set_relation() {
 
 		$query = new WP_Meta_Query( array( array( 'key' => 'abc' ), 'relation' => 'AND' ) );
 
@@ -24,11 +31,25 @@ class Tests_Meta_Query extends WP_UnitTestCase {
 	}
 
 	/**
+	 * Non-arrays should not be added to the queries array
+	 */
+	public function test_invalid_query_clauses() {
+		$query = new WP_Meta_Query( array(
+			'foo', // empty string
+			5, // int
+			false, // bool
+			array(),
+		) );
+
+		$this->assertSame( array( array() ), $query->queries );
+	}
+
+	/**
 	 * Test all key only meta queries use the same INNER JOIN when using relation=OR
 	 *
 	 * @ticket 19729
 	 */
-	function test_single_inner_join_for_keys_only() {
+	public function test_single_inner_join_for_keys_only() {
 
 		global $wpdb;
 
@@ -57,10 +78,78 @@ class Tests_Meta_Query extends WP_UnitTestCase {
 	}
 
 	/**
+	 * WP_Query-style query must be at index 0 for order_by=meta_value to work
+	 */
+	public function test_parse_query_vars_simple_query_index_0() {
+		$qv = array(
+			'meta_query' => array(
+				array(
+					'key' => 'foo1',
+					'compare' => 'baz1',
+					'value' => 'bar1',
+				),
+			),
+			'meta_key' => 'foo',
+			'meta_compare' => 'bar',
+			'meta_value' => 'baz',
+		);
+
+		$query = new WP_Meta_Query();
+		$query->parse_query_vars( $qv );
+
+		$expected0 = array(
+			'key' => 'foo',
+			'compare' => 'bar',
+			'value' => 'baz',
+		);
+		$this->assertEquals( $expected0, $query->queries[0] );
+
+		$expected1 = array(
+			'key' => 'foo1',
+			'compare' => 'baz1',
+			'value' => 'bar1',
+		);
+		$this->assertEquals( $expected1, $query->queries[1] );
+	}
+
+	/**
+	 * When no meta_value is provided, no 'value' should be set in the parsed queries
+	 */
+	public function test_parse_query_vars_with_no_meta_value() {
+		$qv = array(
+			'meta_key' => 'foo',
+			'meta_type' => 'bar',
+			'meta_compare' => '=',
+		);
+
+		$query = new WP_Meta_Query();
+		$query->parse_query_vars( $qv );
+
+		$this->assertTrue( ! isset( $query->queries[0]['value'] ) );
+	}
+
+	/**
+	 * WP_Query sets meta_value to '' by default. It should be removed by parse_query_vars()
+	 */
+	public function test_parse_query_vars_with_default_meta_compare() {
+		$qv = array(
+			'meta_key' => 'foo',
+			'meta_type' => 'bar',
+			'meta_compare' => '=',
+			'meta_value' => '',
+		);
+
+		$query = new WP_Meta_Query();
+		$query->parse_query_vars( $qv );
+
+		$this->assertTrue( ! isset( $query->queries[0]['value'] ) );
+	}
+
+	/**
 	 * Test the conversion between "WP_Query" style meta args (meta_value=x&meta_key=y)
 	 * to a meta query array
 	 */
-	function test_parse_query_vars() {
+	public function test_parse_query_vars() {
 
 		$query = new WP_Meta_Query();
 
@@ -81,9 +170,51 @@ class Tests_Meta_Query extends WP_UnitTestCase {
 	}
 
 	/**
+	 * @ticket 23033
+	 */
+	public function test_get_cast_for_type() {
+		$query = new WP_Meta_Query();
+		$this->assertEquals( 'BINARY', $query->get_cast_for_type( 'BINARY' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'CHAR' ) );
+		$this->assertEquals( 'DATE', $query->get_cast_for_type( 'DATE' ) );
+		$this->assertEquals( 'DATETIME', $query->get_cast_for_type( 'DATETIME' ) );
+		$this->assertEquals( 'SIGNED', $query->get_cast_for_type( 'SIGNED' ) );
+		$this->assertEquals( 'UNSIGNED', $query->get_cast_for_type( 'UNSIGNED' ) );
+		$this->assertEquals( 'TIME', $query->get_cast_for_type( 'TIME' ) );
+		$this->assertEquals( 'SIGNED', $query->get_cast_for_type( 'NUMERIC' ) );
+		$this->assertEquals( 'NUMERIC(10)', $query->get_cast_for_type( 'NUMERIC(10)' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC( 10)' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC( 10 )' ) );
+		$this->assertEquals( 'NUMERIC(10, 5)', $query->get_cast_for_type( 'NUMERIC(10, 5)' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC(10,  5)' ) );
+		$this->assertEquals( 'NUMERIC(10,5)', $query->get_cast_for_type( 'NUMERIC(10,5)' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC( 10, 5 )' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC(10, 5 )' ) );
+		$this->assertEquals( 'DECIMAL', $query->get_cast_for_type( 'DECIMAL' ) );
+		$this->assertEquals( 'DECIMAL(10)', $query->get_cast_for_type( 'DECIMAL(10)' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'DECIMAL( 10 )' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'DECIMAL( 10)' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'DECIMAL(10 )' ) );
+		$this->assertEquals( 'DECIMAL(10, 5)', $query->get_cast_for_type( 'DECIMAL(10, 5)' ) );
+		$this->assertEquals( 'DECIMAL(10,5)', $query->get_cast_for_type( 'DECIMAL(10,5)' ) );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'DECIMAL(10,  5)' ) );
+
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type() );
+		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'ANYTHING ELSE' ) );
+	}
+
+	/**
+	 * Invalid $type will fail to get a table from _get_meta_table()
+	 */
+	public function test_get_sql_invalid_type() {
+		$query = new WP_Meta_Query();
+		$this->assertFalse( $query->get_sql( 'foo', 'foo', 'foo' ) );
+	}
+
+	/**
 	 * @ticket 22096
 	 */
-	function test_empty_value_sql() {
+	public function test_empty_value_sql() {
 		global $wpdb;
 
 		$query = new WP_Meta_Query();
@@ -109,7 +240,7 @@ class Tests_Meta_Query extends WP_UnitTestCase {
 	/**
 	 * @ticket 22967
 	 */
-	function test_null_value_sql() {
+	public function test_null_value_sql() {
 		global $wpdb;
 
 		$query = new WP_Meta_Query( array(
@@ -121,39 +252,276 @@ class Tests_Meta_Query extends WP_UnitTestCase {
 	}
 
 	/**
-	 * @ticket 23033
+	 * "key only queries" are queries that don't need to match a value, so
+	 * they can be grouped together into a single clause without JOINs
 	 */
-	function test_get_cast_for_type() {
-		$query = new WP_Meta_Query();
-		$this->assertEquals( 'BINARY', $query->get_cast_for_type( 'BINARY' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'CHAR' ) );
-		$this->assertEquals( 'DATE', $query->get_cast_for_type( 'DATE' ) );
-		$this->assertEquals( 'DATETIME', $query->get_cast_for_type( 'DATETIME' ) );
-		$this->assertEquals( 'SIGNED', $query->get_cast_for_type( 'SIGNED' ) );
-		$this->assertEquals( 'UNSIGNED', $query->get_cast_for_type( 'UNSIGNED' ) );
-		$this->assertEquals( 'TIME', $query->get_cast_for_type( 'TIME' ) );
-		$this->assertEquals( 'SIGNED', $query->get_cast_for_type( 'NUMERIC' ) );
-		$this->assertEquals( 'NUMERIC(10)', $query->get_cast_for_type( 'NUMERIC(10)' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC( 10)' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC( 10 )' ) );
-		$this->assertEquals( 'NUMERIC(10, 5)', $query->get_cast_for_type( 'NUMERIC(10, 5)' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC(10,  5)' ) );
-		$this->assertEquals( 'NUMERIC(10,5)', $query->get_cast_for_type( 'NUMERIC(10,5)' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC( 10, 5 )' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'NUMERIC(10, 5 )' ) );
-		$this->assertEquals( 'DECIMAL', $query->get_cast_for_type( 'DECIMAL' ) );
-		$this->assertEquals( 'DECIMAL(10)', $query->get_cast_for_type( 'DECIMAL(10)' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'DECIMAL( 10 )' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'DECIMAL( 10)' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'DECIMAL(10 )' ) );
-		$this->assertEquals( 'DECIMAL(10, 5)', $query->get_cast_for_type( 'DECIMAL(10, 5)' ) );
-		$this->assertEquals( 'DECIMAL(10,5)', $query->get_cast_for_type( 'DECIMAL(10,5)' ) );
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'DECIMAL(10,  5)' ) );
+	public function test_get_sql_key_only_queries() {
+		global $wpdb;
 
-		$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'ANYTHING ELSE' ) );
+		$query1 = new WP_Meta_Query( array(
+			'relation' => 'OR',
+
+			// Empty 'compare'
+			array(
+				'key' => 'foo',
+			),
+
+			// Non-empty 'compare'
+			array(
+				'key' => 'bar',
+				'compare' => '<',
+			),
+
+			// NOT EXISTS
+			array(
+				'key' => 'baz',
+				'compare' => 'NOT EXISTS',
+			),
+
+			// Has a value
+			array(
+				'key' => 'barry',
+				'value' => 'foo',
+			),
+
+			// Has no key
+			array(
+				'value' => 'bar',
+			),
+		) );
+
+		$sql = $query1->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		// 'foo' and 'bar' should be queried against the non-aliased table
+		$this->assertSame( 1, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'foo'" ) );
+		$this->assertSame( 1, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'bar'" ) );
+
+		// NOT EXISTS compare queries are not key-only so should not be non-aliased
+		$this->assertSame( 0, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'baz'" ) );
+
+		// When a value exists, it's not a key-only query
+		$this->assertSame( 0, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'barry'" ) );
+
+		// 'AND' queries don't have key-only queries
+		$query2 = new WP_Meta_Query( array(
+			'relation' => 'AND',
+
+			// Empty 'compare'
+			array(
+				'key' => 'foo',
+			),
+
+			// Non-empty 'compare'
+			array(
+				'key' => 'bar',
+				'compare' => '<',
+			),
+		) );
+
+		$sql = $query2->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		// Only 'foo' should be queried against the non-aliased table
+		$this->assertSame( 1, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'foo'" ) );
+		$this->assertSame( 0, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'bar'" ) );
+	}
+
+	/**
+	 * Key-only and regular queries should have the key trimmed
+	 */
+	public function test_get_sql_trim_key() {
+		global $wpdb;
+
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => '  foo  ',
+			),
+			array(
+				'key' => '  bar  ',
+				'value' => 'value',
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "meta_key = 'foo'" ) );
+		$this->assertSame( 1, substr_count( $sql['where'], "meta_key = 'bar'" ) );
+	}
+
+	public function test_convert_null_value_to_empty_string() {
+		global $wpdb;
+
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'value' => null,
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) = ''" ) );
+	}
+
+	public function test_get_sql_convert_lowercase_compare_to_uppercase() {
+		global $wpdb;
+
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'value' => 'bar',
+				'compare' => 'regExp',
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "REGEXP" ) );
+	}
+
+	public function test_get_sql_empty_meta_compare_with_array_value() {
+		global $wpdb;
+
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'value' => array( 'bar', 'baz' ),
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) IN" ) );
+	}
+
+	public function test_get_sql_empty_meta_compare_with_non_array_value() {
+		global $wpdb;
+
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'value' => 'bar',
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) =" ) );
+	}
+
+	public function test_get_sql_invalid_meta_compare() {
+		global $wpdb;
+
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'value' => 'bar',
+				'compare' => 'INVALID COMPARE',
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) =" ) );
+	}
+
+	/**
+	 * This is the clause that ensures that empty arrays are not valid queries
+	 */
+	public function test_get_sql_null_value_and_empty_key_should_not_have_table_join() {
+		global $wpdb;
+
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'value' => 'bar',
+			),
+			array(),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		// There should be no JOIN against an aliased table
+		$this->assertSame( 0, substr_count( $sql['join'], "AS mt" ) );
+	}
+
+	public function test_get_sql_compare_array_comma_separated_values() {
+		global $wpdb;
+
+		// Single
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'compare' => 'IN',
+				'value' => 'bar',
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "('bar')" ) );
+
+		// Multiple, no spaces
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'compare' => 'IN',
+				'value' => 'bar,baz',
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "('bar','baz')" ) );
+
+		// Multiple, spaces
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'compare' => 'IN',
+				'value' => 'bar,baz,   barry',
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "('bar','baz','barry')" ) );
+	}
+
+	public function test_get_sql_compare_array() {
+		global $wpdb;
+
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'compare' => 'IN',
+				'value' => array( 'bar', 'baz' ),
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "('bar','baz')" ) );
+	}
+
+	/**
+	 * Non-array values are trimmed. @todo Why?
+	 */
+	public function test_get_sql_trim_string_value() {
+		global $wpdb;
+
+		$query = new WP_Meta_Query( array(
+			array(
+				'key' => 'foo',
+				'value' => '  bar  ',
+			),
+		) );
+
+		$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+
+		$this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) = 'bar'" ) );
 	}
 
-	function test_not_exists() {
+	public function test_not_exists() {
 		global $wpdb;
 
 		$query = new WP_Meta_Query( array(
@@ -174,7 +542,7 @@ class Tests_Meta_Query extends WP_UnitTestCase {
 		$this->assertContains( "{$wpdb->postmeta}.post_id IS NULL", $sql['where'] );
 	}
 
-	function test_empty_compare() {
+	public function test_empty_compare() {
 		global $wpdb;
 
 		$query = new WP_Meta_Query( array(
diff --git tests/phpunit/tests/post/query.php tests/phpunit/tests/post/query.php
index 004e710..0c565cc 100644
--- tests/phpunit/tests/post/query.php
+++ tests/phpunit/tests/post/query.php
@@ -1,14 +1,433 @@
 <?php
 
-/**
- * @group meta
- */
 class Tests_Post_Query extends WP_UnitTestCase {
 	function setUp() {
 		parent::setUp();
 	}
 
-	function test_meta_key_or_query() {
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_no_key() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'bar' );
+		add_post_meta( $p2, 'oof', 'bar' );
+		add_post_meta( $p3, 'oof', 'baz' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'value' => 'bar',
+				),
+			),
+		) );
+
+		$expected = array( $p1, $p2 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_no_value() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'bar' );
+		add_post_meta( $p2, 'oof', 'bar' );
+		add_post_meta( $p3, 'oof', 'baz' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'oof',
+				),
+			),
+		) );
+
+		$expected = array( $p2, $p3 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_single_query_compare_default() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'bar' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'bar',
+				),
+			),
+		) );
+
+		$expected = array( $p1 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_single_query_compare_equals() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'bar' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'bar',
+					'compare' => '=',
+				),
+			),
+		) );
+
+		$expected = array( $p1 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_single_query_compare_not_equals() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'bar' );
+		add_post_meta( $p2, 'foo', 'baz' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'bar',
+					'compare' => '!=',
+				),
+			),
+		) );
+
+		$expected = array( $p2 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_single_query_compare_arithmetic_comparisons() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', '1' );
+		add_post_meta( $p2, 'foo', '2' );
+		add_post_meta( $p3, 'foo', '3' );
+
+		// <
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 2,
+					'compare' => '<',
+				),
+			),
+		) );
+
+		$expected = array( $p1 );
+		$this->assertEqualSets( $expected, $query->posts );
+
+		// <=
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 2,
+					'compare' => '<=',
+				),
+			),
+		) );
+
+		$expected = array( $p1, $p2 );
+		$this->assertEqualSets( $expected, $query->posts );
+
+		// >=
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 2,
+					'compare' => '>=',
+				),
+			),
+		) );
+
+		$expected = array( $p2, $p3 );
+		$this->assertEqualSets( $expected, $query->posts );
+
+		// >
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 2,
+					'compare' => '>',
+				),
+			),
+		) );
+
+		$expected = array( $p3 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_single_query_compare_like() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'bar' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'ba',
+					'compare' => 'LIKE',
+				),
+			),
+		) );
+
+		$expected = array( $p1 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_single_query_compare_not_like() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'bar' );
+		add_post_meta( $p2, 'foo', 'rab' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'ba',
+					'compare' => 'NOT LIKE',
+				),
+			),
+		) );
+
+		$expected = array( $p2 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_single_query_compare_between_not_between() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', '1' );
+		add_post_meta( $p2, 'foo', '10' );
+		add_post_meta( $p3, 'foo', '100' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => array( 9, 12 ),
+					'compare' => 'BETWEEN',
+					'type' => 'NUMERIC',
+				),
+			),
+		) );
+
+		$expected = array( $p2 );
+		$this->assertEqualSets( $expected, $query->posts );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => array( 9, 12 ),
+					'compare' => 'NOT BETWEEN',
+					'type' => 'NUMERIC',
+				),
+			),
+		) );
+
+		$expected = array( $p1, $p3 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_single_query_compare_regexp_rlike() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'bar' );
+		add_post_meta( $p2, 'foo', 'baz' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'z$',
+					'compare' => 'REGEXP',
+				),
+			),
+		) );
+
+		$expected = array( $p2 );
+		$this->assertEqualSets( $expected, $query->posts );
+
+		// RLIKE is a synonym for REGEXP
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'z$',
+					'compare' => 'RLIKE',
+				),
+			),
+		) );
+
+		$expected = array( $p2 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_single_query_compare_not_regexp() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'bar' );
+		add_post_meta( $p2, 'foo', 'baz' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'z$',
+					'compare' => 'NOT REGEXP',
+				),
+			),
+		) );
+
+		$expected = array( $p1 );
+		$this->assertEqualSets( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_relation_default() {
+		$p1 = $this->factory->post->create();
+		$p2 = $this->factory->post->create();
+		$p3 = $this->factory->post->create();
+
+		add_post_meta( $p1, 'foo', 'foo value 1' );
+		add_post_meta( $p1, 'bar', 'bar value 1' );
+		add_post_meta( $p2, 'foo', 'foo value 1' );
+		add_post_meta( $p2, 'bar', 'bar value 2' );
+
+		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'foo value 1',
+				),
+				array(
+					'key' => 'bar',
+					'value' => 'bar value 1',
+				),
+			),
+		) );
+
+		$expected = array( $p1 );
+		$this->assertEquals( $expected, $query->posts );
+	}
+
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_relation_or() {
 		$post_id = $this->factory->post->create();
 		add_post_meta( $post_id, 'foo', rand_str() );
 		add_post_meta( $post_id, 'foo', rand_str() );
@@ -24,6 +443,9 @@ class Tests_Post_Query extends WP_UnitTestCase {
 		add_post_meta( $post_id6, 'bar', 'val1' );
 
 		$query = new WP_Query( array(
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 			'meta_query' => array(
 				array(
 					'key' => 'foo'
@@ -42,18 +464,14 @@ class Tests_Post_Query extends WP_UnitTestCase {
 			),
 		) );
 
-		$posts = $query->get_posts();
-		$this->assertEquals( 4, count( $posts ) );
-		foreach ( $posts as $post ) {
-			$this->assertInstanceOf( 'WP_Post', $post );
-			$this->assertEquals( 'raw', $post->filter );
-		}
-
-		$post_ids = wp_list_pluck( $posts, 'ID' );
-		$this->assertEqualSets( array( $post_id, $post_id2, $post_id3, $post_id4 ), $post_ids );
+		$expected = array( $post_id, $post_id2, $post_id3, $post_id4 );
+		$this->assertEqualSets( $expected, $query->posts );
 	}
 
-	function test_meta_key_and_query() {
+	/**
+	 * @group meta
+	 */
+	public function test_meta_query_relation_and() {
 		$post_id = $this->factory->post->create();
 		add_post_meta( $post_id, 'foo', rand_str() );
 		add_post_meta( $post_id, 'foo', rand_str() );
@@ -92,17 +510,13 @@ class Tests_Post_Query extends WP_UnitTestCase {
 				),
 				'relation' => 'AND',
 			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
 
-		$posts = $query->get_posts();
-		$this->assertEquals( 1, count( $posts ) );
-		foreach ( $posts as $post ) {
-			$this->assertInstanceOf( 'WP_Post', $post );
-			$this->assertEquals( 'raw', $post->filter );
-		}
-
-		$post_ids = wp_list_pluck( $posts, 'ID' );
-		$this->assertEquals( array( $post_id7 ), $post_ids );
+		$expected = array( $post_id7 );
+		$this->assertEqualSets( $expected, $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
@@ -114,23 +528,20 @@ class Tests_Post_Query extends WP_UnitTestCase {
 				),
 				'relation' => 'AND',
 			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
 
-		$posts = $query->get_posts();
-		$this->assertEquals( 3, count( $posts ) );
-		foreach ( $posts as $post ) {
-			$this->assertInstanceOf( 'WP_Post', $post );
-			$this->assertEquals( 'raw', $post->filter );
-		}
-
-		$post_ids = wp_list_pluck( $posts, 'ID' );
-		$this->assertEqualSets( array( $post_id2, $post_id6, $post_id7 ), $post_ids );
+		$expected = array( $post_id2, $post_id6, $post_id7 );
+		$this->assertEqualSets( $expected, $query->posts );
 	}
 
 	/**
 	 * @ticket 18158
+	 * @group meta
 	 */
-	function test_meta_key_not_exists() {
+	public function test_meta_query_compare_not_exists() {
 		$post_id = $this->factory->post->create();
 		add_post_meta( $post_id, 'foo', rand_str() );
 		$post_id2 = $this->factory->post->create();
@@ -144,65 +555,66 @@ class Tests_Post_Query extends WP_UnitTestCase {
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-			array(
-				'key' => 'foo',
-				'compare' => 'NOT EXISTS',
-			),
+				array(
+					'key' => 'foo',
+					'compare' => 'NOT EXISTS',
+				),
 			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
 
-		$posts = $query->get_posts();
-		$this->assertEquals( 3, count( $posts ) );
-		foreach ( $posts as $post ) {
-			$this->assertInstanceOf( 'WP_Post', $post );
-			$this->assertEquals( 'raw', $post->filter );
-		}
+		$expected = array( $post_id2, $post_id3, $post_id4 );
+		$this->assertEqualSets( $expected, $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-			array(
-				'key' => 'foo',
-				'compare' => 'NOT EXISTS',
-			),
 				array(
-				'key' => 'bar',
-				'compare' => 'NOT EXISTS',
-			),
+					'key' => 'foo',
+					'compare' => 'NOT EXISTS',
+				),
+				array(
+					'key' => 'bar',
+					'compare' => 'NOT EXISTS',
+				),
 			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
 
-		$posts = $query->get_posts();
-		$this->assertEquals( 1, count( $posts ) );
-		foreach ( $posts as $post ) {
-			$this->assertInstanceOf( 'WP_Post', $post );
-			$this->assertEquals( 'raw', $post->filter );
-		}
+		$expected = array( $post_id4 );
+		$this->assertEquals( $expected, $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-			array(
-				'key' => 'foo',
-				'compare' => 'NOT EXISTS',
-			),
 				array(
-				'key' => 'bar',
-				'compare' => 'NOT EXISTS',
-			),
+					'key' => 'foo',
+					'compare' => 'NOT EXISTS',
+				),
 				array(
-				'key' => 'baz',
-				'compare' => 'NOT EXISTS',
+					'key' => 'bar',
+					'compare' => 'NOT EXISTS',
+				),
+				array(
+					'key' => 'baz',
+					'compare' => 'NOT EXISTS',
+				),
 			),
-			)
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
 
-		$posts = $query->get_posts();
-		$this->assertEquals( 0, count( $posts ) );
+		$this->assertEquals( 0, count( $query->posts ) );
 	}
 
 	/**
 	 * @ticket 23033
+	 * @group meta
 	 */
-	function test_meta_query_decimal_results() {
+	public function test_meta_query_decimal_results() {
 		$post_1 = $this->factory->post->create();
 		$post_2 = $this->factory->post->create();
 		$post_3 = $this->factory->post->create();
@@ -215,121 +627,149 @@ class Tests_Post_Query extends WP_UnitTestCase {
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-					array(
-						'key' => 'decimal_value',
-						'value' => '.300',
-						'compare' => '=',
-						'type' => 'DECIMAL(10,2)'
-					)
-				),
+				array(
+					'key' => 'decimal_value',
+					'value' => '.300',
+					'compare' => '=',
+					'type' => 'DECIMAL(10,2)'
+				)
+			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_3 ), wp_list_pluck( $query->posts, 'ID' ) );
+		$this->assertEqualSets( array( $post_3 ), $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-					array(
-						'key' => 'decimal_value',
-						'value' => '0.35',
-						'compare' => '>',
-						'type' => 'DECIMAL(10,2)'
-					)
-				),
+				array(
+					'key' => 'decimal_value',
+					'value' => '0.35',
+					'compare' => '>',
+					'type' => 'DECIMAL(10,2)'
+				)
+			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_4 ), wp_list_pluck( $query->posts, 'ID' ) );
+		$this->assertEqualSets( array( $post_4 ), $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-					array(
-						'key' => 'decimal_value',
-						'value' => '0.3',
-						'compare' => '>=',
-						'type' => 'DECIMAL(10,2)'
-					)
-				),
+				array(
+					'key' => 'decimal_value',
+					'value' => '0.3',
+					'compare' => '>=',
+					'type' => 'DECIMAL(10,2)'
+				)
+			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_3, $post_4 ), wp_list_pluck( $query->posts, 'ID' ) );
+		$this->assertEqualSets( array( $post_3, $post_4 ), $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-					array(
-						'key' => 'decimal_value',
-						'value' => '0',
-						'compare' => '<',
-						'type' => 'DECIMAL(10,2)'
-					)
-				),
+				array(
+					'key' => 'decimal_value',
+					'value' => '0',
+					'compare' => '<',
+					'type' => 'DECIMAL(10,2)'
+				)
+			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_1 ), wp_list_pluck( $query->posts, 'ID' ) );
+		$this->assertEqualSets( array( $post_1 ), $query->posts, 'ID' );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-					array(
-						'key' => 'decimal_value',
-						'value' => '0.3',
-						'compare' => '<=',
-						'type' => 'DECIMAL(10,2)'
-					)
-				),
-
+				array(
+					'key' => 'decimal_value',
+					'value' => '0.3',
+					'compare' => '<=',
+					'type' => 'DECIMAL(10,2)'
+				)
+			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_1, $post_2, $post_3 ), wp_list_pluck( $query->posts, 'ID' ) );
+		$this->assertEqualSets( array( $post_1, $post_2, $post_3 ), $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-					array(
-						'key' => 'decimal_value',
-						'value' => array( 0.23409845, .31 ),
-						'compare' => 'BETWEEN',
-						'type' => 'DECIMAL(10, 10)'
-					)
-				),
+				array(
+					'key' => 'decimal_value',
+					'value' => array( 0.23409845, .31 ),
+					'compare' => 'BETWEEN',
+					'type' => 'DECIMAL(10, 10)'
+				)
+			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_3 ), wp_list_pluck( $query->posts, 'ID' ) );
+		$this->assertEqualSets( array( $post_3 ), $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-					array(
-						'key' => 'decimal_value',
-						'value' => array( 0.23409845, .31 ),
-						'compare' => 'NOT BETWEEN',
-						'type' => 'DECIMAL(10,10)'
-					)
-				),
+				array(
+					'key' => 'decimal_value',
+					'value' => array( 0.23409845, .31 ),
+					'compare' => 'NOT BETWEEN',
+					'type' => 'DECIMAL(10,10)'
+				)
+			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_1, $post_2, $post_4 ), wp_list_pluck( $query->posts, 'ID' ) );
+		$this->assertEqualSets( array( $post_1, $post_2, $post_4 ), $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-					array(
-						'key' => 'decimal_value',
-						'value' => '.3',
-						'compare' => 'LIKE',
-						'type' => 'DECIMAL(10,2)'
-					)
-				),
+				array(
+					'key' => 'decimal_value',
+					'value' => '.3',
+					'compare' => 'LIKE',
+					'type' => 'DECIMAL(10,2)'
+				)
+			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_1, $post_3 ), wp_list_pluck( $query->posts, 'ID' ) );
+		$this->assertEqualSets( array( $post_1, $post_3 ), $query->posts );
 
 		$query = new WP_Query( array(
 			'meta_query' => array(
-					array(
-						'key' => 'decimal_value',
-						'value' => '.3',
-						'compare' => 'NOT LIKE',
-						'type' => 'DECIMAL(10,2)'
-					)
-				),
+				array(
+					'key' => 'decimal_value',
+					'value' => '.3',
+					'compare' => 'NOT LIKE',
+					'type' => 'DECIMAL(10,2)'
+				)
+			),
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_2, $post_4 ), wp_list_pluck( $query->posts, 'ID' ) );
+		$this->assertEqualSets( array( $post_2, $post_4 ), $query->posts );
 
 		$query = new WP_Query( array(
 			'orderby' => 'meta_value',
 			'order' => 'DESC',
 			'meta_key' => 'decimal_value',
-			'meta_type' => 'DECIMAL(10, 2)'
+			'meta_type' => 'DECIMAL(10, 2)',
+			'update_post_meta_cache' => false,
+			'update_post_term_cache' => false,
+			'fields' => 'ids',
 		) );
-		$this->assertEqualSets( array( $post_4, $post_3, $post_2, $post_1 ), wp_list_pluck( $query->posts, 'ID' ) );
-
+		$this->assertEqualSets( array( $post_4, $post_3, $post_2, $post_1 ), $query->posts );
 	}
 
 	/**
@@ -831,4 +1271,4 @@ class Tests_Post_Query extends WP_UnitTestCase {
 			$q3->request
 		);
 	}
-}
\ No newline at end of file
+}
