From dcb47ed24d54665f87ce61bb1f8dc9761a9f219b Mon Sep 17 00:00:00 2001
From: Angie Byron <webchick@24967.no-reply.drupal.org>
Date: Wed, 17 Feb 2010 05:24:53 +0000
Subject: [PATCH] #706248 by bellHead and Damien Tournoud: Fixed
 field_sql_storage_field_storage_query() with 'count' option breaks on
 PostgreSQL and SQLite. (with tests)

---
 includes/database/select.inc                  | 29 ++++++++++++-------
 .../field_sql_storage.module                  |  8 +++--
 modules/simpletest/tests/database_test.test   | 13 +++++++++
 3 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/includes/database/select.inc b/includes/database/select.inc
index f3fd8368a949..b071c7454287 100644
--- a/includes/database/select.inc
+++ b/includes/database/select.inc
@@ -1250,17 +1250,19 @@ public function countQuery() {
     // Create our new query object that we will mutate into a count query.
     $count = clone($this);
 
-    // Zero-out existing fields and expressions.
-    $fields =& $count->getFields();
-    $fields = array();
-    $expressions =& $count->getExpressions();
-    $expressions = array();
-
+    if (!$count->distinct) {
+      // When not executing a distinct query, we can zero-out existing fields
+      // and expressions.
+      $fields =& $count->getFields();
+      $fields = array();
+      $expressions =& $count->getExpressions();
+      $expressions = array();
 
-    // Also remove 'all_fields' statements, which are expanded into tablename.*
-    // when the query is executed.
-    foreach ($count->tables as $alias => &$table) {
-      unset($table['all_fields']);
+      // Also remove 'all_fields' statements, which are expanded into tablename.*
+      // when the query is executed.
+      foreach ($count->tables as $alias => &$table) {
+        unset($table['all_fields']);
+      }
     }
 
     // Ordering a count query is a waste of cycles, and breaks on some
@@ -1268,6 +1270,13 @@ public function countQuery() {
     $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);
+      $count->distinct = FALSE;
+    }
+
     // COUNT() is an expression, so we add that back in.
     $count->addExpression('COUNT(*)');
 
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.module b/modules/field/modules/field_sql_storage/field_sql_storage.module
index b0d0ed4c4109..8229c523f33d 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.module
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.module
@@ -539,8 +539,12 @@ function field_sql_storage_field_storage_query($field_id, $conditions, $options)
 
   // For a count query, return the count now.
   if ($options['count']) {
-    $query->addExpression('COUNT(DISTINCT e.type,t.entity_id,t.revision_id)');
-    return $query->execute()->fetchField();
+    return $query
+      ->fields('t', array('etid', 'entity_id', 'revision_id'))
+      ->distinct()
+      ->countQuery()
+      ->execute()
+      ->fetchField();
   }
 
   // For a data query, add fields.
diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test
index 19ecbe6e9769..cf569f7cc65e 100644
--- a/modules/simpletest/tests/database_test.test
+++ b/modules/simpletest/tests/database_test.test
@@ -1908,6 +1908,19 @@ class DatabaseSelectComplexTestCase extends DatabaseTestCase {
     $this->assertEqual($count, 4, t('Counted the correct number of records.'));
   }
 
+  /**
+   * Test that we can generate a count query from a query with distinct.
+   */
+  function testCountQueryDistinct() {
+    $query = db_select('test_task');
+    $task_field = $query->addField('test_task', 'task');
+    $query->distinct();
+
+    $count = $query->countQuery()->execute()->fetchField();
+
+    $this->assertEqual($count, 6, t('Counted the correct number of records.'));
+  }
+
   /**
    * Confirm that we can properly nest conditional clauses.
    */
-- 
GitLab