From 98f287b55a88d06199cda88b6929af589c182e23 Mon Sep 17 00:00:00 2001 From: Angie Byron <webchick@24967.no-reply.drupal.org> Date: Fri, 31 Dec 2010 20:43:43 +0000 Subject: [PATCH] #1001242 by agentrickard, pwolanin, Crell, chx: Add DBTNG support for EXISTS conditions. --- includes/database/query.inc | 86 +++++++++++++++++++++ includes/database/select.inc | 32 +++++++- modules/simpletest/tests/database_test.test | 55 +++++++++++++ 3 files changed, 172 insertions(+), 1 deletion(-) diff --git a/includes/database/query.inc b/includes/database/query.inc index 7c590c2200da..de421b30c1d1 100644 --- a/includes/database/query.inc +++ b/includes/database/query.inc @@ -76,6 +76,28 @@ public function isNull($field); */ public function isNotNull($field); + /** + * Sets a condition that the specified subquery returns values. + * + * @param SelectQueryInterface $select + * The subquery that must contain results. + * + * @return QueryConditionInterface + * The called object. + */ + public function exists(SelectQueryInterface $select); + + /** + * Sets a condition that the specified subquery returns no values. + * + * @param SelectQueryInterface $select + * The subquery that must not contain results. + * + * @return QueryConditionInterface + * The called object. + */ + public function notExists(SelectQueryInterface $select); + /** * Gets a complete list of all conditions in this conditional clause. * @@ -726,6 +748,22 @@ public function isNotNull($field) { return $this; } + /** + * Implements QueryConditionInterface::exists(). + */ + public function exists(SelectQueryInterface $select) { + $this->condition->exists($select); + return $this; + } + + /** + * Implements QueryConditionInterface::notExists(). + */ + public function notExists(SelectQueryInterface $select) { + $this->condition->notExists($select); + return $this; + } + /** * Implements QueryConditionInterface::conditions(). */ @@ -946,6 +984,22 @@ public function isNotNull($field) { return $this; } + /** + * Implements QueryConditionInterface::exists(). + */ + public function exists(SelectQueryInterface $select) { + $this->condition->exists($select); + return $this; + } + + /** + * Implements QueryConditionInterface::notExists(). + */ + public function notExists(SelectQueryInterface $select) { + $this->condition->notExists($select); + return $this; + } + /** * Implements QueryConditionInterface::conditions(). */ @@ -1416,6 +1470,22 @@ public function isNotNull($field) { return $this; } + /** + * Implements QueryConditionInterface::exists(). + */ + public function exists(SelectQueryInterface $select) { + $this->condition->exists($select); + return $this; + } + + /** + * Implements QueryConditionInterface::notExists(). + */ + public function notExists(SelectQueryInterface $select) { + $this->condition->notExists($select); + return $this; + } + /** * Implements QueryConditionInterface::conditions(). */ @@ -1614,6 +1684,20 @@ public function isNotNull($field) { return $this->condition($field, NULL, 'IS NOT NULL'); } + /** + * Implements QueryConditionInterface::exists(). + */ + public function exists(SelectQueryInterface $select) { + return $this->condition('', $select, 'EXISTS'); + } + + /** + * Implements QueryConditionInterface::notExists(). + */ + public function notExists(SelectQueryInterface $select) { + return $this->condition('', $select, 'NOT EXISTS'); + } + /** * Implements QueryConditionInterface::conditions(). */ @@ -1756,6 +1840,8 @@ protected function mapConditionOperator($operator) { 'BETWEEN' => array('delimiter' => ' AND '), 'IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'), 'NOT IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'), + 'EXISTS' => array('prefix' => ' (', 'postfix' => ')'), + 'NOT EXISTS' => array('prefix' => ' (', 'postfix' => ')'), 'IS NULL' => array('use_value' => FALSE), 'IS NOT NULL' => array('use_value' => FALSE), // Use backslash for escaping wildcard characters. diff --git a/includes/database/select.inc b/includes/database/select.inc index 7f44063a2a02..43f92671e3c4 100644 --- a/includes/database/select.inc +++ b/includes/database/select.inc @@ -810,6 +810,16 @@ function isNotNull($field) { return $this; } + public function exists(SelectQueryInterface $select) { + $this->query->exists($select); + return $this; + } + + public function notExists(SelectQueryInterface $select) { + $this->query->notExists($select); + return $this; + } + public function __toString() { return (string) $this->query; } @@ -1022,6 +1032,16 @@ public function isNotNull($field) { return $this; } + public function exists(SelectQueryInterface $select) { + $this->where->exists($select); + return $this; + } + + public function notExists(SelectQueryInterface $select) { + $this->where->notExists($select); + return $this; + } + public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder = NULL) { return $this->where->compile($connection, isset($queryPlaceholder) ? $queryPlaceholder : $this); } @@ -1069,7 +1089,17 @@ public function havingIsNotNull($field) { $this->having->isNotNull($field); return $this; } - + + public function havingExists(SelectQueryInterface $select) { + $this->having->exists($select); + return $this; + } + + public function havingNotExists(SelectQueryInterface $select) { + $this->having->notExists($select); + return $this; + } + public function forUpdate($set = TRUE) { if (isset($set)) { $this->forUpdate = $set; diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test index bfd67de9d5af..243dbba31e77 100644 --- a/modules/simpletest/tests/database_test.test +++ b/modules/simpletest/tests/database_test.test @@ -1684,6 +1684,61 @@ class DatabaseSelectSubqueryTestCase extends DatabaseTestCase { $this->assertEqual(count($people), 2, t('Returned the correct number of rows.')); } + + /** + * Test EXISTS subquery conditionals on SELECT statements. + */ + function testExistsSubquerySelect() { + // Put George into {test_people}. + db_insert('test_people') + ->fields(array( + 'name' => 'George', + 'age' => 27, + 'job' => 'Singer', + )) + ->execute(); + // Base query to {test}. + $query = db_select('test', 't') + ->fields('t', array('name')); + // Subquery to {test_people}. + $subquery = db_select('test_people', 'tp') + ->fields('tp', array('name')) + ->condition('name', 'George'); + $query->exists($subquery); + $result = $query->execute(); + + // Ensure that we got the right record. + $record = $result->fetch(); + $this->assertEqual($record->name, 'George', t('Fetched name is correct using EXISTS query.')); + } + + /** + * Test NOT EXISTS subquery conditionals on SELECT statements. + */ + function testNotExistsSubquerySelect() { + // Put George into {test_people}. + db_insert('test_people') + ->fields(array( + 'name' => 'George', + 'age' => 27, + 'job' => 'Singer', + )) + ->execute(); + + // Base query to {test}. + $query = db_select('test', 't') + ->fields('t', array('name')); + // Subquery to {test_people}. + $subquery = db_select('test_people', 'tp') + ->fields('tp', array('name')) + ->condition('name', 'George'); + $query->notExists($subquery); + $result = $query->execute(); + + // Ensure that we got the right record. + $record = $result->fetch(); + $this->assertFalse($record, t('NOT EXISTS query returned no results.')); + } } /** -- GitLab