Index: includes/database/select.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/select.inc,v
retrieving revision 1.41
diff -u -p -r1.41 select.inc
--- includes/database/select.inc	15 May 2010 07:04:21 -0000	1.41
+++ includes/database/select.inc	24 May 2010 18:01:38 -0000
@@ -94,6 +94,24 @@ interface SelectQueryInterface extends Q
   public function &getOrderBy();
 
   /**
+   * Returns a reference to the group by array for this query.
+   *
+   * Because this method returns by reference, alter hooks may edit the order-by
+   * array directly to make their changes. If just adding additional ordering
+   * fields, however, the use of groupBy() is preferred.
+   *
+   * Note that this method must be called by reference as well:
+   *
+   * @code
+   * $fields =& $query->getGroupBy();
+   * @endcode
+   *
+   * @return
+   *   A reference to the expression array structure.
+   */
+  public function &getGroupBy();
+
+  /**
    * Returns a reference to the tables array for this query.
    *
    * Because this method returns by reference, alter hooks may edit the tables
@@ -622,6 +640,10 @@ class SelectQueryExtender implements Sel
     return $this->query->getOrderBy();
   }
 
+  public function &getGroupBy() {
+    return $this->query->getGroupBy();
+  }
+
   public function &getTables() {
     return $this->query->getTables();
   }
@@ -1029,6 +1051,10 @@ class SelectQuery extends Query implemen
     return $this->order;
   }
 
+  public function &getGroupBy() {
+    return $this->group;
+  }
+
   public function &getTables() {
     return $this->tables;
   }
@@ -1282,13 +1308,24 @@ class SelectQuery extends Query implemen
     // Create our new query object that we will mutate into a count query.
     $count = clone($this);
 
+    $group_by = array_keys($count->getGroupBy());
+
     if (!$count->distinct) {
       // When not executing a distinct query, we can zero-out existing fields
-      // and expressions.
+      // and expressions that are not used by a GROUP BY.  Fields listed in
+      // the GROUP BY clause need to be present in the query.
       $fields =& $count->getFields();
-      $fields = array();
+      foreach (array_keys($fields) as $field) {
+        if (!empty($group_by[$field])) {
+          unset($fields[$field]);
+        }
+      }
       $expressions =& $count->getExpressions();
-      $expressions = array();
+      foreach (array_keys($expressions) as $field) {
+        if (!empty($group_by[$field])) {
+          unset($fields[$field]);
+        }
+      }
 
       // Also remove 'all_fields' statements, which are expanded into tablename.*
       // when the query is executed.
@@ -1297,22 +1334,25 @@ class SelectQuery extends Query implemen
       }
     }
 
+    // If we've just removed all fields from the query, make sure there is at
+    // least one so that the query still runs.
+    $count->addExpression('1');
+
     // Ordering a count query is a waste of cycles, and breaks on some
     // databases anyway.
     $orders = &$count->getOrderBy();
     $orders = array();
 
-    if ($count->distinct) {
-      // If the query is distinct, we need to execute it in a subquery,
-      // because SQL99 does not support counting on distinct multiple fields.
-      $count = db_select($count);
+    if ($count->distinct && !empty($group_by)) {
+      // If the query is distinct and contains a GROUP BY, we need to remove the
+      // distinct because SQL99 does not support counting on distinct multiple fields.
       $count->distinct = FALSE;
     }
 
-    // COUNT() is an expression, so we add that back in.
-    $count->addExpression('COUNT(*)');
+    $query = db_select($count);
+    $query->addExpression('COUNT(*)');
 
-    return $count;
+    return $query;
   }
 
   public function __toString() {
Index: modules/simpletest/tests/database_test.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.test,v
retrieving revision 1.92
diff -u -p -r1.92 database_test.test
--- modules/simpletest/tests/database_test.test	15 May 2010 07:04:21 -0000	1.92
+++ modules/simpletest/tests/database_test.test	24 May 2010 18:01:39 -0000
@@ -1977,6 +1977,19 @@ class DatabaseSelectComplexTestCase exte
   }
 
   /**
+   * Test that we can generate a count query from a query with GROUP BY.
+   */
+  function testCountQueryGroupBy() {
+    $query = db_select('test_task');
+    $pid_field = $query->addField('test_task', 'pid');
+    $query->groupBy('pid');
+
+    $count = $query->countQuery()->execute()->fetchField();
+
+    $this->assertEqual($count, 3, t('Counted the correct number of records.'));
+  }
+
+  /**
    * Confirm that we can properly nest conditional clauses.
    */
   function testNestedConditions() {
