From 82ba1702dfb866a11f74cd9b4dbccf228b848ae8 Mon Sep 17 00:00:00 2001 From: Scott Taylor Date: Mon, 24 Mar 2014 19:56:54 +0000 Subject: [PATCH] When using `meta_query` in a `WP_Query`, passing `NOT EXISTS` or `''` to `compare` should not require `value` to be set. The resulting SQL should then produce the appropriate `OR` clause for existence of non-existence after passing the query to the `$key_only_queries` stack internally. Adds unit tests. Props chrisguitarguy, for the original patch. Fixes #23268. git-svn-id: https://develop.svn.wordpress.org/trunk@27689 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/meta.php | 2 +- tests/phpunit/tests/meta/query.php | 42 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/meta.php b/src/wp-includes/meta.php index dc19833612..b3a06c9681 100644 --- a/src/wp-includes/meta.php +++ b/src/wp-includes/meta.php @@ -753,7 +753,7 @@ class WP_Meta_Query { // Split out the meta_key only queries (we can only do this for OR) if ( 'OR' == $this->relation ) { foreach ( $this->queries as $k => $q ) { - if ( ! array_key_exists( 'value', $q ) && ! empty( $q['key'] ) ) + if ( ( empty( $q['compare'] ) || 'NOT EXISTS' != $q['compare'] ) && ! array_key_exists( 'value', $q ) && ! empty( $q['key'] ) ) $key_only_queries[$k] = $q; else $queries[$k] = $q; diff --git a/tests/phpunit/tests/meta/query.php b/tests/phpunit/tests/meta/query.php index ef668ab04a..fdd7693f79 100644 --- a/tests/phpunit/tests/meta/query.php +++ b/tests/phpunit/tests/meta/query.php @@ -152,4 +152,46 @@ class Tests_Meta_Query extends WP_UnitTestCase { $this->assertEquals( 'CHAR', $query->get_cast_for_type( 'ANYTHING ELSE' ) ); } + + function test_not_exists() { + global $wpdb; + + $query = new WP_Meta_Query( array( + 'relation' => 'OR', + array( + 'key' => 'exclude', + 'compare' => 'NOT EXISTS' + ), + array( + 'key' => 'exclude', + 'compare' => '!=', + 'value' => '1' + ), + ) ); + + $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this ); + $this->assertNotContains( "{$wpdb->postmeta}.meta_key = 'exclude'\nOR", $sql['where'] ); + $this->assertContains( "{$wpdb->postmeta}.post_id IS NULL", $sql['where'] ); + } + + function test_empty_compare() { + global $wpdb; + + $query = new WP_Meta_Query( array( + 'relation' => 'OR', + array( + 'key' => 'exclude', + 'compare' => '' + ), + array( + 'key' => 'exclude', + 'compare' => '!=', + 'value' => '1' + ), + ) ); + + $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this ); + $this->assertContains( "{$wpdb->postmeta}.meta_key = 'exclude'\nOR", $sql['where'] ); + $this->assertNotContains( "{$wpdb->postmeta}.post_id IS NULL", $sql['where'] ); + } }