diff --git a/src/wp-includes/meta.php b/src/wp-includes/meta.php index 17bc82ea04..afbf954a1c 100644 --- a/src/wp-includes/meta.php +++ b/src/wp-includes/meta.php @@ -1123,6 +1123,14 @@ class WP_Meta_Query { $sql = $this->get_sql_clauses(); + /* + * If any JOINs are LEFT JOINs (as in the case of NOT EXISTS), then all JOINs should + * be LEFT. Otherwise posts with no metadata will be excluded from results. + */ + if ( false !== strpos( $sql['join'], 'LEFT JOIN' ) ) { + $sql['join'] = str_replace( 'INNER JOIN', 'LEFT JOIN', $sql['join'] ); + } + /** * Filter the meta query's generated SQL. * diff --git a/tests/phpunit/tests/post/query.php b/tests/phpunit/tests/post/query.php index ad36158fa4..0d6d50eaa5 100644 --- a/tests/phpunit/tests/post/query.php +++ b/tests/phpunit/tests/post/query.php @@ -610,6 +610,42 @@ class Tests_Post_Query extends WP_UnitTestCase { $this->assertEquals( 0, count( $query->posts ) ); } + /** + * @ticket 29062 + */ + public function test_meta_query_compare_not_exists_with_another_condition_relation_or() { + $posts = $this->factory->post->create_many( 4 ); + update_post_meta( $posts[0], 'color', 'orange' ); + update_post_meta( $posts[1], 'color', 'blue' ); + update_post_meta( $posts[1], 'vegetable', 'onion' ); + update_post_meta( $posts[2], 'vegetable', 'shallot' ); + + $post_3_meta = get_post_meta( $posts[3] ); + foreach ( $post_3_meta as $meta_key => $meta_value ) { + delete_post_meta( $posts[3], $meta_key ); + } + + $query = new WP_Query( array( + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'vegetable', + 'value' => 'onion', + ), + array( + 'key' => 'color', + 'compare' => 'NOT EXISTS', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[1], $posts[2], $posts[3] ); + $this->assertEqualSets( $expected, $query->posts ); + } + /** * @ticket 23033 * @group meta