? 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 .')'; - // (? 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; }