diff --git a/includes/database/query.inc b/includes/database/query.inc
index 23b652f..da839cb 100644
--- a/includes/database/query.inc
+++ b/includes/database/query.inc
@@ -23,16 +23,18 @@ interface QueryConditionInterface {
    * value of IN if $value is an array and = otherwise.
    *
    * @param $field
-   *   The name of the field to check. If you would like to add a more complex
-   *   condition involving operators or functions, use where().
+   *   The name of the field to check. This can also be a SelectQueryInterface
+   *   or a QueryConditionInterface in itself. If you would like to add a more
+   *   complex condition involving operators or functions, use where().
    * @param $value
-   *   The value to test the field against. In most cases, this is a scalar.
-   *   For more complex options, it is an array. The meaning of each element in
-   *   the array is dependent on the $operator.
+   *   The value to test the field against. In most cases, and depending on the
+   *   operator, this will be a scalar or an array. As SQL accepts select
+   *   queries on any place where a value or set is expected, $value may also be
+   *   a(n array of) SelectQueryInterface('s).
    * @param $operator
    *   The comparison operator, such as =, <, or >=. It also accepts more
-   *   complex options such as IN, LIKE, or BETWEEN. Defaults to IN if $value is
-   *   an array, and = otherwise.
+   *   complex options such as IN, LIKE, or BETWEEN. Defaults to = if $value is
+   *   a scalar, to IN if $value is an array, and to IS NULL if $value is null.
    *
    * @return QueryConditionInterface
    *   The called object.
@@ -77,7 +79,7 @@ interface QueryConditionInterface {
 
   /**
    * Sets a condition that the specified subquery returns values.
-   * 
+   *
    * @param SelectQueryInterface $select
    *   The subquery that must contain results.
    *
@@ -85,10 +87,10 @@ interface 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.
    *
@@ -96,7 +98,7 @@ interface QueryConditionInterface {
    *   The called object.
    */
   public function notExists(SelectQueryInterface $select);
-  
+
   /**
    * Gets a complete list of all conditions in this conditional clause.
    *
@@ -264,14 +266,14 @@ abstract class Query implements QueryPlaceholderInterface {
 
   /**
    * The target of the connection object.
-   * 
+   *
    * @var string
    */
   protected $connectionTarget;
 
   /**
    * The key of the connection object.
-   * 
+   *
    * @var string
    */
   protected $connectionKey;
@@ -764,7 +766,7 @@ class DeleteQuery extends Query implements QueryConditionInterface {
     $this->condition->notExists($select);
     return $this;
   }
-  
+
   /**
    * Implements QueryConditionInterface::conditions().
    */
@@ -999,7 +1001,7 @@ class UpdateQuery extends Query implements QueryConditionInterface {
     $this->condition->notExists($select);
     return $this;
   }
-  
+
   /**
    * Implements QueryConditionInterface::conditions().
    */
@@ -1484,7 +1486,7 @@ class MergeQuery extends Query implements QueryConditionInterface {
     $this->condition->notExists($select);
     return $this;
   }
-  
+
   /**
    * Implements QueryConditionInterface::conditions().
    */
@@ -1637,12 +1639,12 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
       if (is_array($value)) {
         $operator = 'IN';
       }
-      elseif (!isset($value)) {
-        $operator = 'IS NULL';
-      }
-      else {
+      elseif (isset($value)) {
         $operator = '=';
       }
+      else if (!($field instanceof QueryConditionInterface)) {
+        $operator = 'IS NULL';
+      }
     }
     $this->conditions[] = array(
       'field' => $field,
@@ -1689,14 +1691,14 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
   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().
    */
@@ -1727,67 +1729,97 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
       $conjunction = $conditions['#conjunction'];
       unset($conditions['#conjunction']);
       foreach ($conditions as $condition) {
-        if (empty($condition['operator'])) {
-          // This condition is a literal string, so let it through as is.
-          $condition_fragments[] = ' (' . $condition['field'] . ') ';
+        // Process field.
+        if ($condition['field'] instanceof QueryConditionInterface) {
+          // Left hand part is a structured condition or a subquery: compile,
+          // put brackets around it if it is a query, and collect any arguments.
+          $condition['field']->compile($connection, $queryPlaceholder);
+          $field_fragment = (string) $condition['field'];
+          if ($condition['field'] instanceof SelectQueryInterface) {
+            $field_fragment = '(' . $field_fragment . ')';
+          }
+          $arguments += $condition['field']->arguments();
+        }
+        else if (empty($condition['operator'])) {
+          // Left hand part is a literal string added with the
+          // @see QueryConditionInterface::where() method. Put brackets around
+          // the snippet and collect the arguments from the value part.
+          $field_fragment = '(' . $condition['field'] . ')';
           $arguments += $condition['value'];
         }
         else {
-          // It's a structured condition, so parse it out accordingly.
-          // Note that $condition['field'] will only be an object for a dependent
-          // DatabaseCondition object, not for a dependent subquery.
-          if ($condition['field'] instanceof QueryConditionInterface) {
-            // Compile the sub-condition recursively and add it to the list.
-            $condition['field']->compile($connection, $queryPlaceholder);
-            $condition_fragments[] = '(' . (string) $condition['field'] . ')';
-            $arguments += $condition['field']->arguments();
+          // Left hand part is a normal field: add it as is.
+          $field_fragment = $condition['field'];
+        }
+
+        // Process operator. For simplicity, we convert all operators to a data
+        // structure to allow to specify a prefix, a delimeter and such.
+        if (!isset($condition['operator'])) {
+          // Empty operator: the field is assumed to be a valid condition on its
+          // own. Ignore the operator and value parts.
+          $operator = array('operator' => '', 'use_value' => FALSE);
+        }
+        else {
+          // Operator is a string. Find the associated data structure by first
+          // doing a database specific lookup, followed by a specification
+          // according to the SQL standard.
+          $operator = $connection->mapConditionOperator($condition['operator']);
+          if (!isset($operator)) {
+            $operator = $this->mapConditionOperator($condition['operator']);
           }
-          else {
-            // For simplicity, we treat all operators as the same data structure.
-            // In the typical degenerate case, this won't get changed.
-            $operator_defaults = array(
-              'prefix' => '',
-              'postfix' => '',
-              'delimiter' => '',
-              'operator' => $condition['operator'],
-              'use_value' => TRUE,
-            );
-            $operator = $connection->mapConditionOperator($condition['operator']);
-            if (!isset($operator)) {
-              $operator = $this->mapConditionOperator($condition['operator']);
-            }
-            $operator += $operator_defaults;
-
-            $placeholders = array();
-            if ($condition['value'] instanceof SelectQueryInterface) {
-              $condition['value']->compile($connection, $queryPlaceholder);
-              $placeholders[] = (string) $condition['value'];
-              $arguments += $condition['value']->arguments();
-              // Subqueries are the actual value of the operator, we don't
-              // need to add another below.
-              $operator['use_value'] = FALSE;
+          $operator += array('operator' => $condition['operator']);
+        }
+        $operator += array(
+          'prefix' => '',
+          'postfix' => '',
+          'delimiter' => '',
+          'use_value' => TRUE,
+        );
+        $operator_fragment = $operator['operator'];
+
+        // Process value.
+        $value_fragment = '';
+        if ($operator['use_value']) {
+          // For simplicity, we first convert to an array, so that we can handle
+          // the single and multi value cases the same.
+          if (!is_array($condition['value'])) {
+            if ($operator['operator'] == 'IN' && $condition['value'] instanceof QueryConditionInterface) {
+              // Special case: IN is followed by a select query instead of a set
+              // of values: unset prefix and postfix to prevent double brackets.
+              $operator['prefix'] = '';
+              $operator['postfix'] = '';
             }
-            // We assume that if there is a delimiter, then the value is an
-            // array. If not, it is a scalar. For simplicity, we first convert
-            // up to an array so that we can build the placeholders in the same way.
-            elseif (!$operator['delimiter']) {
-              $condition['value'] = array($condition['value']);
+            $condition['value'] = array($condition['value']);
+          }
+          // Process all separate values.
+          $value_fragment = array();
+          foreach ($condition['value'] as $value) {
+            if ($value instanceof QueryConditionInterface) {
+              // Right hand part is a subquery: compile, assure that brackets
+              // are put around it and collect any arguments.
+              $value->compile($connection, $queryPlaceholder);
+              $value_fragment[] = '(' . (string) $value . ')';
+              $arguments += $value->arguments();
             }
-            if ($operator['use_value']) {
-              foreach ($condition['value'] as $value) {
-                $placeholder = ':db_condition_placeholder_' . $queryPlaceholder->nextPlaceholder();
-                $arguments[$placeholder] = $value;
-                $placeholders[] = $placeholder;
-              }
+            else {
+              // Right hand part is a normal value: replace the value with a
+              // placeholder and add the value as an argument.
+              $placeholder = ':db_condition_placeholder_' . $queryPlaceholder->nextPlaceholder();
+              $value_fragment[] = $placeholder;
+              $arguments[$placeholder] = $value;
             }
-            $condition_fragments[] = ' (' . $connection->escapeField($condition['field']) . ' ' . $operator['operator'] . ' ' . $operator['prefix'] . implode($operator['delimiter'], $placeholders) . $operator['postfix'] . ') ';
           }
+          $value_fragment = $operator['prefix'] . implode($operator['delimiter'], $value_fragment) . $operator['postfix'];
         }
+        // Concatenate the left hand part, operator and right hand part.
+        $condition_fragments[] = trim(implode(' ', array($field_fragment, $operator_fragment, $value_fragment)));
       }
 
-      $this->changed = FALSE;
-      $this->stringVersion = implode($conjunction, $condition_fragments);
+      // Concatenate all conditions using the conjunction and brackets around
+      // the individual conditions to assure the proper evaluation order.
+      $this->stringVersion = count($condition_fragments) > 1 ? '(' . implode(") $conjunction (", $condition_fragments) . ')' : implode($condition_fragments);
       $this->arguments = $arguments;
+      $this->changed = FALSE;
     }
   }
 
@@ -1837,10 +1869,10 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
     // $specials does not use drupal_static as its value never changes.
     static $specials = array(
       'BETWEEN' => array('delimiter' => ' AND '),
-      'IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
-      'NOT IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
-      'EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
-      'NOT EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
+      '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/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test
index c22d1fc..22dd186 100644
--- a/modules/simpletest/tests/database_test.test
+++ b/modules/simpletest/tests/database_test.test
@@ -1674,7 +1674,7 @@ class DatabaseSelectSubqueryTestCase extends DatabaseTestCase {
   }
 
   /**
-   * Test that we can use a subquery in a WHERE clause.
+   * Test that we can use a subquery with an IN operator in a WHERE clause.
    */
   function testConditionSubquerySelect() {
     // Create a subquery, which is just a normal query object.
@@ -1697,6 +1697,55 @@ class DatabaseSelectSubqueryTestCase extends DatabaseTestCase {
   }
 
   /**
+   * Test that we can use a subquery with a relational operator in a WHERE clause.
+   */
+  function testConditionSubquerySelect2() {
+    // Create a subquery, which is just a normal query object.
+    $subquery = db_select('test', 't2');
+    $subquery->addExpression('AVG(t2.age)');
+
+    // Create another query that adds a clause using the subquery.
+    $select = db_select('test', 't');
+    $select->addField('t', 'name');
+    $select->condition('t.age', $subquery, '<');
+
+    // The resulting query should be equivalent to:
+    // SELECT t.name
+    // FROM test t
+    // WHERE t.age < (SELECT AVG(t2.age) FROM test t2)
+    $people = $select->execute()->fetchCol();
+    $this->assertEqual(count($people), 2, t('Returned the correct number of rows.'));
+    $this->assertTrue(in_array('Paul', $people) && in_array('John', $people), t('Returned Paul and John.'));
+  }
+
+  /**
+   * Test that we can use 2 subqueries with a relational operator in a WHERE clause.
+   */
+  function testConditionSubquerySelect3() {
+    // Create subquery 1, which is just a normal query object.
+    $subquery1 = db_select('test_task', 'tt');
+    $subquery1->addExpression('AVG(tt.priority)');
+    $subquery1->where('tt.pid = t.id');
+
+    // Create subquery 2, which is just a normal query object.
+    $subquery2 = db_select('test_task', 'tt2');
+    $subquery2->addExpression('AVG(tt2.priority)');
+
+    // Create another query that adds a clause using the subqueries.
+    $select = db_select('test', 't');
+    $select->addField('t', 'name');
+    $select->condition($subquery1, $subquery2, '>');
+
+    // The resulting query should be equivalent to:
+    // SELECT t.name
+    // FROM test t
+    // WHERE (SELECT AVG(tt.priority) FROM test_task tt WHERE tt.pid = t.id) > (SELECT AVG(tt2.priority) FROM test_task tt2)
+    $people = $select->execute()->fetchCol();
+    $this->assertEqual(count($people), 1, t('Returned the correct number of rows.'));
+    $this->assertTrue(in_array('John', $people), t('Returned John.'));
+  }
+
+  /**
    * Test that we can use a subquery in a JOIN clause.
    */
   function testJoinSubquerySelect() {
