? db_distinct_2.patch
? db_distinct_3.patch
? files
? installtxtupdate_1.patch
? urlencode.patch
? modules/filter/filter.admin.inc
? modules/filter/filter.pages.inc
? sites/here.be.dragons.rtk0.net
Index: includes/database.mysql-common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.mysql-common.inc,v
retrieving revision 1.11
diff -u -p -r1.11 database.mysql-common.inc
--- includes/database.mysql-common.inc	7 Sep 2007 10:42:56 -0000	1.11
+++ includes/database.mysql-common.inc	11 Sep 2007 19:26:00 -0000
@@ -7,6 +7,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
  * @{
  */
Index: includes/database.mysql.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v
retrieving revision 1.79
diff -u -p -r1.79 database.mysql.inc
--- includes/database.mysql.inc	29 Aug 2007 18:38:55 -0000	1.79
+++ includes/database.mysql.inc	11 Sep 2007 19:26:00 -0000
@@ -379,24 +379,6 @@ function db_table_exists($table) {
 function db_column_exists($table, $column) {
   return db_fetch_object(db_query("SHOW COLUMNS FROM {%s} LIKE '%s'", $table, $column)) ? TRUE : FALSE;
 }
-
-/**
- * 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".
  */
Index: includes/database.mysqli.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.mysqli.inc,v
retrieving revision 1.44
diff -u -p -r1.44 database.mysqli.inc
--- includes/database.mysqli.inc	3 Sep 2007 17:02:16 -0000	1.44
+++ includes/database.mysqli.inc	11 Sep 2007 19:26:00 -0000
@@ -378,24 +378,6 @@ function db_table_exists($table) {
 function db_column_exists($table, $column) {
   return db_fetch_object(db_query("SHOW COLUMNS FROM {%s} LIKE '%s'", $table, $column)) ? TRUE : FALSE;
 }
-
-/**
- * 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".
  */
Index: includes/database.pgsql.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.pgsql.inc,v
retrieving revision 1.59
diff -u -p -r1.59 database.pgsql.inc
--- includes/database.pgsql.inc	7 Sep 2007 10:42:56 -0000	1.59
+++ includes/database.pgsql.inc	11 Sep 2007 19:26:00 -0000
@@ -435,10 +435,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;
 }
 
