=== modified file 'includes/database.mysql-common.inc'
--- includes/database.mysql-common.inc	2007-05-30 09:11:21 +0000
+++ includes/database.mysql-common.inc	2007-05-31 20:08:39 +0000
@@ -8,6 +8,51 @@
  */
 
 /**
+ * @ingroup database
+ * @{
+ */
+
+/**
+ * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to
+ * the SELECT list entry of the given query and the resulting query is returned.
+ * This function only applies the wrapper if a DISTINCT doesn't already exist in
+ * the query.
+ *
+ * @param $table Table containing the field to set as DISTINCT
+ * @param $field Field to set as DISTINCT
+ * @param $query Query to apply the wrapper to
+ * @return SQL query with the DISTINCT wrapper surrounding the given table.field.
+ */
+function db_distinct_field($table, $field, $query) {
+  /*
+   * Rewrite rule: (t: $table, f: $field)
+   *
+   * (1) SELECT .... FROM .... {some}_table t ....
+   *  => SELECT .... FROM .... (SELECT * FROM {some}_table GROUP BY f) t ....
+   *
+   * (2) Remove DISTINCT or DISTINCTROW
+   *     SELECT DISTINCT .... FROM ....
+   *  => SELECT          .... FROM ....
+   *
+   * (3) Remove pgsql specific syntax SELECT DISTINCT ON (...)
+   *     SELECT .... DISTINCT ON (....) ....
+   *  => SELECT ....                    ....
+   */
+
+  $query = preg_replace('/\s+DISTINCT(ROW)?(\s+ON\s*\([^\)]*\))?/si', "", $query);
+  if (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/si', '(SELECT * FROM \1 GROUP BY ' . $field . ') \2 ', $m[2]);
+    $query .= $m[3];
+  }
+  return $query;
+}
+
+/**
+ * @} End of "ingroup database".
+ */
+
+/**
  * @ingroup schemaapi
  * @{
  */
@@ -450,5 +495,3 @@ function db_update_field(&$ret, $table, 
 /**
  * @} End of "ingroup schemaapi".
  */
-
-?>
\ No newline at end of file

=== modified file 'includes/database.mysql.inc'
--- includes/database.mysql.inc	2007-05-25 21:01:29 +0000
+++ includes/database.mysql.inc	2007-05-31 20:09:10 +0000
@@ -416,24 +416,6 @@ function db_table_exists($table) {
 function db_column_exists($table, $column) {
   return db_num_rows(db_query("SHOW COLUMNS FROM {%s} LIKE '%s'", $table, $column));
 }
-
-/**
- * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to
- * the SELECT list entry of the given query and the resulting query is returned.
- * This function only applies the wrapper if a DISTINCT doesn't already exist in
- * the query.
- *
- * @param $table Table containing the field to set as DISTINCT
- * @param $field Field to set as DISTINCT
- * @param $query Query to apply the wrapper to
- * @return SQL query with the DISTINCT wrapper surrounding the given table.field.
- */
-function db_distinct_field($table, $field, $query) {
-  $field_to_select = 'DISTINCT('. $table .'.'. $field .')';
-  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
-  return preg_replace('/(SELECT.*)(?:'. $table .'\.|\s)(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1 '. $field_to_select .'\2', $query);
-}
-
 /**
  * @} End of "ingroup database".
  */

=== modified file 'includes/database.mysqli.inc'
--- includes/database.mysqli.inc	2007-05-25 21:01:29 +0000
+++ includes/database.mysqli.inc	2007-05-31 20:09:04 +0000
@@ -408,24 +408,6 @@ function db_table_exists($table) {
 function db_column_exists($table, $column) {
   return db_num_rows(db_query("SHOW COLUMNS FROM {%s} LIKE '%s'", $table, $column));
 }
-
-/**
- * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to
- * the SELECT list entry of the given query and the resulting query is returned.
- * This function only applies the wrapper if a DISTINCT doesn't already exist in
- * the query.
- *
- * @param $table Table containing the field to set as DISTINCT
- * @param $field Field to set as DISTINCT
- * @param $query Query to apply the wrapper to
- * @return SQL query with the DISTINCT wrapper surrounding the given table.field.
- */
-function db_distinct_field($table, $field, $query) {
-  $field_to_select = 'DISTINCT('. $table .'.'. $field .')';
-  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
-  return preg_replace('/(SELECT.*)(?:'. $table .'\.|\s)(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1 '. $field_to_select .'\2', $query);
-}
-
 /**
  * @} End of "ingroup database".
  */

=== modified file 'includes/database.pgsql.inc'
--- includes/database.pgsql.inc	2007-05-30 09:11:21 +0000
+++ includes/database.pgsql.inc	2007-05-31 20:10:17 +0000
@@ -461,10 +461,26 @@ function db_check_setup() {
  * @return SQL query with the DISTINCT wrapper surrounding the given table.field.
  */
 function db_distinct_field($table, $field, $query) {
-  $field_to_select = 'DISTINCT ON ('. $table .'.'. $field .") $table.$field";
-  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
-  $query = preg_replace('/(SELECT.*)(?:'. $table .'\.|\s)(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1 '. $field_to_select .'\2', $query);
-  $query = preg_replace('/(ORDER BY )(?!'. $table .'\.'. $field .')/', '\1'."$table.$field, ", $query);
+  // Rewrite rules:
+  //
+  // (1) SELECT .... FROM .... {some}_table t ....
+  //  => SELECT .... FROM .... (SELECT DISTINCT ON (primary_field) * FROM {some}_table) t ....
+  //
+  // (2) Don't rewrite SELECT DISTINCT ON (t.n)
+  //     SELECT DISTINCT ON (t.n) .... FROM .... {some}_table t ....
+  //  => SELECT DISTINCT ON (t.n) .... FROM .... {some}_table t ....
+  //
+  //     SELECT DISTINCT ON (n) .... FROM .... {some}_table t ....
+  //  => SELECT DISTINCT ON (t.n) .... FROM .... {some}_table t ....
+  //
+  // (3) SELECT DISTINCT ON (...., t.n, ....) .... FROM .... {some}_table t ....
+  //  => SELECT DISTINCT ON (...., t.n, ....) .... FROM .... (SELECT DISTINCT ON (f)// FROM {some}_table) t ....
+  if (!preg_match('/DISTINCT\s+ON\s*\(\s*('. $table .'\s*\.\s*)?'. $field .'\s*\)/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];
+  }
   return $query;
 }
 

