diff --git a/includes/database.inc b/includes/database.inc index 3cb55d06b0370a984520c816a85bed253ac3d511..26e59619d6370d9a273a2916d03761ca0db4b3a6 100644 --- a/includes/database.inc +++ b/includes/database.inc @@ -261,9 +261,7 @@ function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $ list($join, $where, $distinct) = _db_rewrite_sql($query, $primary_table, $primary_field, $args); if ($distinct) { - $field_to_select = 'DISTINCT('. $primary_table .'.'. $primary_field .')'; - // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT). - $query = preg_replace('/(SELECT.*)('. $primary_table .'\.)?(?<!DISTINCT\()(?<!DISTINCT\('. $primary_table .'\.)'. $primary_field .'(.*FROM )/AUsi', '\1'. $field_to_select .'\3', $query); + $query = db_distinct_field($primary_table, $primary_field, $query); } if (!empty($where) || !empty($join)) { diff --git a/includes/database.mysql.inc b/includes/database.mysql.inc index b0ffd2692b7a9698a52fb05f7cfbc6891cd1cce8..18eeee019e9aba0704b1fb5e159409dc041d14c8 100644 --- a/includes/database.mysql.inc +++ b/includes/database.mysql.inc @@ -417,6 +417,23 @@ function db_table_exists($table) { return db_num_rows(db_query("SHOW TABLES LIKE '{" . db_escape_table($table) . "}'")); } +/** + * 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 .'\.)?(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1'. $field_to_select .'\3', $query); +} + /** * @} End of "ingroup database". */ diff --git a/includes/database.mysqli.inc b/includes/database.mysqli.inc index 7cc5943b70b572fde7f2e8d21d0eac37eaf01ec0..7e9ba9dcb5b5ac14d7c6c27c694f63f0374894e1 100644 --- a/includes/database.mysqli.inc +++ b/includes/database.mysqli.inc @@ -412,6 +412,23 @@ function db_table_exists($table) { return db_num_rows(db_query("SHOW TABLES LIKE '{" . db_escape_table($table) . "}'")); } +/** + * 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 .'\.)?(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1'. $field_to_select .'\3', $query); +} + /** * @} End of "ingroup database". */ diff --git a/includes/database.pgsql.inc b/includes/database.pgsql.inc index b5b53b9551c2c27ae5f19dfe53c25de545f26afc..14a9a502518394d2e4527b88405944145d154cc7 100644 --- a/includes/database.pgsql.inc +++ b/includes/database.pgsql.inc @@ -400,6 +400,25 @@ function db_check_setup() { } } +/** + * 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 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 .'\.)?(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1'. $field_to_select .'\3', $query); + $query = preg_replace('/(ORDER BY )(?!'.$table.'\.'.$field.')/', '\1'."$table.$field, ", $query); + return $query; +} + /** * @} End of "ingroup database". */