From 1a7bac90e75ad36ea5d9c3e97baeddd87435ed52 Mon Sep 17 00:00:00 2001 From: Neil Drumm <drumm@3064.no-reply.drupal.org> Date: Mon, 23 Oct 2006 18:38:45 +0000 Subject: [PATCH] #76819 by smsimms and sammys. Move part of the sql rewriting down into the database abstraction layer and add extra rewriting needed only for Postgres. --- includes/database.inc | 4 +--- includes/database.mysql.inc | 17 +++++++++++++++++ includes/database.mysqli.inc | 17 +++++++++++++++++ includes/database.pgsql.inc | 19 +++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/includes/database.inc b/includes/database.inc index 3cb55d06b037..26e59619d637 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 b0ffd2692b7a..18eeee019e9a 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 7cc5943b70b5..7e9ba9dcb5b5 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 b5b53b9551c2..14a9a5025183 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". */ -- GitLab