? .buildpath
? .project
? .settings
? db_rewrite_and_tests-D6.3.patch
? db_rewrite_and_tests-D6.4.patch
? modules/system/tests
? scripts/run-tests.sh
? sites/all/modules
? sites/default/files
? sites/default/settings.php
Index: includes/database.mysql.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/Attic/database.mysql.inc,v
retrieving revision 1.89.2.1
diff -u -r1.89.2.1 database.mysql.inc
--- includes/database.mysql.inc	21 Jul 2009 08:52:29 -0000	1.89.2.1
+++ includes/database.mysql.inc	4 Dec 2009 19:13:21 -0000
@@ -365,7 +365,7 @@
   $matches = array();
   if (preg_match('/^SELECT(.*?)FROM(.*)/is', $query, $matches)) {
     $select = preg_replace(
-      '/((?:^|,)\s*)(?<!DISTINCT\()(?:'. $table .'\.)?'. $field .'(\s*(?:,|$))/is',
+      '/((?:^|,|\()\s*)(?<!DISTINCT\()(?:'. $table .'\.)?'. $field .'(\s*(?:,|\sAS|\)|$))/is',
       '\1'. $field_to_select .'\2', $matches[1], 1
     );
     
Index: includes/database.mysqli.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/Attic/database.mysqli.inc,v
retrieving revision 1.54.2.1
diff -u -r1.54.2.1 database.mysqli.inc
--- includes/database.mysqli.inc	21 Jul 2009 08:52:30 -0000	1.54.2.1
+++ includes/database.mysqli.inc	4 Dec 2009 19:13:21 -0000
@@ -367,7 +367,7 @@
   $matches = array();
   if (preg_match('/^SELECT(.*?)FROM(.*)/is', $query, $matches)) {
     $select = preg_replace(
-      '/((?:^|,)\s*)(?<!DISTINCT\()(?:'. $table .'\.)?'. $field .'(\s*(?:,|$))/is',
+      '/((?:^|,|\()\s*)(?<!DISTINCT\()(?:'. $table .'\.)?'. $field .'(\s*(?:,|\sAS|\)|$))/is',
       '\1'. $field_to_select .'\2', $matches[1], 1
     );
     
Index: includes/database.pgsql.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/Attic/database.pgsql.inc,v
retrieving revision 1.68.2.7
diff -u -r1.68.2.7 database.pgsql.inc
--- includes/database.pgsql.inc	14 Sep 2009 10:49:34 -0000	1.68.2.7
+++ includes/database.pgsql.inc	4 Dec 2009 19:13:21 -0000
@@ -419,14 +419,68 @@
  * @return SQL query with the DISTINCT wrapper surrounding the given table.field.
  */
 function db_distinct_field($table, $field, $query) {
+  //var_dump($table, $field, $query);
+  // The first regex tries to avoids touching the query if we have a subquery
+  // The second avoids messing with the query if there is alerady a distinct, this may or may not be a good idea
+
   if (!preg_match('/FROM\s+\S+\s+AS/si', $query)
-  && !preg_match('/DISTINCT\s+ON\s*\(\s*(' . $table . '\s*\.\s*)?' . $field . '\s*\)/si', $query)
-  && !preg_match('/DISTINCT[ (]' . $field . '/si', $query)
-  && preg_match('/(.*FROM\s+)(.*?\s)(\s*(WHERE|GROUP|HAVING|ORDER|LIMIT|FOR).*)/Asi', $query, $m)) {
-    $query = $m[1];
-    $query .= preg_replace('/([\{\w+\}]+)\s+(' . $table . ')\s/Usi', '(SELECT DISTINCT ON (' . $field . ') * FROM \1) \2 ', $m[2]);
-    $query .= $m[3];
+  && !preg_match('/DISTINCT\s+ON\s*\(\s*(' . $table . '\s*\.\s*)?' . $field . '\s*\)/si', $query)) {
+    $matches = array();
+    if (preg_match('/DISTINCT[ (]' . preg_quote($table .'.'. $field) . '/si', $query, $matches)) {
+      // We should replace DISTINCT(), which doesn't do anything different than DISTINCT on the whole query
+      // with a DISTINCT ON.  However, as DISTINCT() n ever works on either MySql or PostgreSQL (at least in postgres
+      // 8.4.1 and MySQL 5.1.37, this may have unintended consequences.  So we leave the query as is for now.
+      ;
+    }
+    else {
+      $qualified_primary_field = $table .'.'. $field;
+
+      $regex = '/^SELECT\s+(.*?)\s+FROM\s+(.*?)(ORDER BY\s+(.*?))?(LIMIT.*|OFFSET.*|\s*$)/is';
+      //var_dump ($regex);
+      if (preg_match($regex, $query, $matches)) {
+        //$matches[1] is the select list
+        //$matches[2] is everything after FROM and before ORDER BY
+        //$matches[3] is the order by as a whole (if it exists)
+        //$matches[4] is the order by content (if it exists)
+        //$matches[5] is the rest of the query
+        //var_dump($matches);
+
+        // If there is an ORDER BY, modify it to make sure that the primary
+        // field is at the begining (Postgres must have the content of
+        // distinct on at the begining of the order by (if there is an ORDER
+        // BY)
+        if(!empty($matches[3])) {
+          $order_by_elements = preg_split  ('/\s*,\s*/', $matches[4]);
+          $key_found = FALSE;
+          foreach($order_by_elements as $key=>$value) {
+            if(strstr($value, $qualified_primary_field)) {
+              $key_found = $key;
+              break;
+            }
+          }
+          if($key_found!==FALSE) {
+            $prepend_to_order_by = $order_by_elements[$key_found];
+            unset($order_by_elements[$key_found]);
+          }
+          else {
+            $prepend_to_order_by = $qualified_primary_field;
+          }
+          array_unshift($order_by_elements, $prepend_to_order_by);
+          $order_by = 'ORDER BY ' . implode(', ', $order_by_elements);
+        }
+        else {
+          $order_by = '';
+        }
+        $field_to_select = 'DISTINCT ON ('.$qualified_primary_field.') '.$qualified_primary_field;
+        $field_to_select_count = 'DISTINCT('.$qualified_primary_field.')';
+        $patterns = array('/' . preg_quote($qualified_primary_field) . '(?=\s|,|$)/', '/(?<=COUNT\()' . preg_quote($qualified_primary_field) . '(?=\))/');
+        $replacements = array($field_to_select, $field_to_select_count);
+        $select_list_replacement = preg_replace($patterns, $replacements, $matches[1]);
+        $query = preg_replace($regex,"SELECT $select_list_replacement FROM \\2$order_by\\5", $query);
+      }
+    }
   }
+  //var_dump($query);
   return $query;
 }
 
