diff --git a/includes/database.inc b/includes/database.inc index 6e396d9f586aac5bb2ba8a7d43c4ba11448627e3..0fe516ad56e9dc5bc9e23e941a2972bda1006b8c 100644 --- a/includes/database.inc +++ b/includes/database.inc @@ -388,6 +388,27 @@ function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $ return $query; } +/** + * Adds the DISTINCT flag to the supplied query if a DISTINCT doesn't already + * exist in the query. Returns the altered query. + * + * This will not, and never did guarantee that you will obtain distinct + * values of $table.$field. + * + * @param $table Unused. Kept to remain API compatibility. + * @param $field Unused. Kept to remain API compatibility. + * @param $query Query to which the DISTINCT flag should be applied. + * @return SQL query with the DISTINCT flag set. + */ +function db_distinct_field($table, $field, $query) { + $matches = array(); + if (!preg_match('/^SELECT\s*DISTINCT/i', $query, $matches)) { + // Only add distinct to the outer SELECT to avoid messing up subqueries. + $query = preg_replace('/^SELECT/i', 'SELECT DISTINCT', $query); + } + return $query; +} + /** * Restrict a dynamic table, column or constraint name to safe characters. * diff --git a/includes/database.mysql.inc b/includes/database.mysql.inc index 14f4f6cb95d0f8b157f09cd2362a1e60a5cde874..7d177c8967ab7115bb7dc27beb691bc8f2e80811 100644 --- a/includes/database.mysql.inc +++ b/includes/database.mysql.inc @@ -349,31 +349,6 @@ function db_column_exists($table, $column) { return (bool) db_fetch_object(db_query("SHOW COLUMNS FROM {". db_escape_table($table) ."} LIKE '". db_escape_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 .')'; - $matches = array(); - if (preg_match('/^SELECT(.*?)FROM(.*)/is', $query, $matches)) { - $select = preg_replace( - '/((?:^|,)\s*)(?<!DISTINCT\()(?:'. $table .'\.)?'. $field .'(\s*(?:,|$))/is', - '\1'. $field_to_select .'\2', $matches[1], 1 - ); - - return 'SELECT'. $select .'FROM'. $matches[2]; - } - return $query; -} - /** * @} End of "ingroup database". */ diff --git a/includes/database.mysqli.inc b/includes/database.mysqli.inc index 7e7d9983d5654ff1c1d402d15c9375d4626083e4..70a9943ef0b368de3ee7d467ce5ce7981684cfc2 100644 --- a/includes/database.mysqli.inc +++ b/includes/database.mysqli.inc @@ -351,31 +351,6 @@ function db_column_exists($table, $column) { return (bool) db_fetch_object(db_query("SHOW COLUMNS FROM {". db_escape_table($table) ."} LIKE '". db_escape_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 .')'; - $matches = array(); - if (preg_match('/^SELECT(.*?)FROM(.*)/is', $query, $matches)) { - $select = preg_replace( - '/((?:^|,)\s*)(?<!DISTINCT\()(?:'. $table .'\.)?'. $field .'(\s*(?:,|$))/is', - '\1'. $field_to_select .'\2', $matches[1], 1 - ); - - return 'SELECT'. $select .'FROM'.$matches[2]; - } - return $query; -} - /** * @} End of "ingroup database". */ diff --git a/includes/database.pgsql.inc b/includes/database.pgsql.inc index da6dc83b7be90f8c4c5af79dd48ce1232c8e2d08..32ae48e0bb31092f5934bce7911022a95f39f319 100644 --- a/includes/database.pgsql.inc +++ b/includes/database.pgsql.inc @@ -407,29 +407,6 @@ 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) { - 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]; - } - return $query; -} - /** * @} End of "ingroup database". */