? .buildpath ? .project ? .settings ? 284392-simplify-db_distinct_fields-rev3.D6.patch ? 284392-simplify-with-tests-db_distinct_fields-rev4.D6.patch ? db_rewrite_and_tests-D6.3.patch ? db_rewrite_and_tests-D6.4.patch ? db_rewrite_and_tests-D6.5.patch ? db_rewrite_and_tests-D6.6.patch ? scripts/run-tests.sh ? sites/default/files ? sites/default/settings.php ? sites/default/settings.php.mysql ? sites/default/settings.php.postgres Index: includes/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/Attic/database.inc,v retrieving revision 1.92.2.8 diff -u -p -r1.92.2.8 database.inc --- includes/database.inc 14 Sep 2009 10:49:34 -0000 1.92.2.8 +++ includes/database.inc 18 Dec 2009 23:17:13 -0000 @@ -389,6 +389,27 @@ function db_rewrite_sql($query, $primary } /** + * 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, garantee 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. * * Only keeps alphanumeric and underscores. Index: includes/database.mysql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/Attic/database.mysql.inc,v retrieving revision 1.89.2.1 diff -u -p -r1.89.2.1 database.mysql.inc --- includes/database.mysql.inc 21 Jul 2009 08:52:29 -0000 1.89.2.1 +++ includes/database.mysql.inc 18 Dec 2009 23:17:13 -0000 @@ -350,30 +350,5 @@ function db_column_exists($table, $colum } /** - * 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*)(? t('Database functionality'), + 'description' => t('Exercise the database helper functions, this not not test the database but the functions that abstract the database.'), + 'group' => t('Database'), + ); + } + + + /** + * Test the db_distinct_field() function. + * + * See http://drupal.org/node/284392 for more information + */ + function testDbDistinctField() { + // These assertions are taken from: + // http://drupal.org/node/284392 + + $assertions[] = array( + 'input' => array("table", "field", "SELECT table.field FROM table"), + 'expected' => 'SELECT DISTINCT table.field FROM table', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT table.field AS table_field FROM table"), + 'expected' => 'SELECT DISTINCT table.field AS table_field FROM table', + ); + + // Questionnable, "SELECT DISTINCT table.field FROM table" would also be + // appropriate. But it must NOT return + // SELECT DISTINCT DISTINCT(table.field) FROM table + $assertions[] = array( + 'input' => array("table", "field", "SELECT DISTINCT(table.field) FROM table"), + 'expected' => 'SELECT DISTINCT(table.field) FROM table', + ); + + // Same comment as previous test + $assertions[] = array( + 'input' => array("table", "field", "SELECT DISTINCT(table.field) AS table_field FROM table"), + 'expected' => 'SELECT DISTINCT(table.field) AS table_field FROM table', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT DISTINCT table.field AS table_field FROM table"), + 'expected' => 'SELECT DISTINCT table.field AS table_field FROM table', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT DISTINCT * AS table_field FROM table"), + 'expected' => 'SELECT DISTINCT * AS table_field FROM table', + ); + + // + $assertions[] = array( + 'input' => array("table", "field", "SELECT table.field,table.field2 FROM table"), + 'expected' => 'SELECT DISTINCT table.field,table.field2 FROM table', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT table.field AS table_field, table.field2 AS table_field2 FROM table"), + 'expected' => 'SELECT DISTINCT table.field AS table_field, table.field2 AS table_field2 FROM table', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT DISTINCT(table.field),table.field2 FROM table"), + 'expected' => 'SELECT DISTINCT(table.field),table.field2 FROM table', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT DISTINCT(table.field) AS table_field, table.field2 AS table_field2 FROM table"), + 'expected' => 'SELECT DISTINCT(table.field) AS table_field, table.field2 AS table_field2 FROM table', + ); + + // COUNT() may not be the only field, so it still makes sense to do DISTINCT + $assertions[] = array( + 'input' => array("table", "field", "SELECT COUNT(table.field) FROM table"), + 'expected' => 'SELECT DISTINCT COUNT(table.field) FROM table', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT table.field1, COUNT(table.field), table.field2 FROM table"), + 'expected' => 'SELECT DISTINCT table.field1, COUNT(table.field), table.field2 FROM table', + ); + + //Yes, that's weird, but it's legal + $assertions[] = array( + 'input' => array("table", "field", "SELECT COUNT(DISTINCT(table.field)) FROM table"), + 'expected' => 'SELECT DISTINCT COUNT(DISTINCT(table.field)) FROM table', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT COUNT(*) FROM table"), + 'expected' => 'SELECT DISTINCT COUNT(*) FROM table', + ); + + // Check that we don't accidentally chop anything off the end of the query + $assertions[] = array( + 'input' => array("table", "field", "SELECT table.field FROM table ORDER BY foo.bar LIMIT 10"), + 'expected' => 'SELECT DISTINCT table.field FROM table ORDER BY foo.bar LIMIT 10', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT table.field FROM table LIMIT 10"), + 'expected' => 'SELECT DISTINCT table.field FROM table LIMIT 10', + ); + + $assertions[] = array( + 'input' => array("table", "field", "SELECT table.field FROM (SELECT * FROM table2) AS table2_sub"), + 'expected' => 'SELECT DISTINCT table.field FROM (SELECT * FROM table2) AS table2_sub', + ); + + foreach ($assertions as $assert) { + $distinct_added = call_user_func_array('db_distinct_field', $assert['input']); + if (!$this->assertEqual( + $distinct_added, + $assert['expected'], + t('Add DISTINCT to %query', array('%query' => $assert['input'][2])) + )) { + $this->pass(t('Query was rewritten to: %query, expected query: %expected_query', array('%query' => $distinct_added, '%expected_query' => $assert['expected']))); + } + } + + + + + + } + + +}