Index: includes/database/select.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/select.inc,v
retrieving revision 1.4
diff -u -p -r1.4 select.inc
--- includes/database/select.inc	15 Sep 2008 05:00:48 -0000	1.4
+++ includes/database/select.inc	18 Oct 2008 23:41:47 -0000
@@ -37,6 +37,7 @@ class SelectQuery extends Query implemen
    *   'alias' => $alias_of_the_table,
    *   'condition' => $condition_clause_on_which_to_join,
    *   'arguments' => $array_of_arguments_for_placeholders_in_the condition.
+   *   'all_fields' => TRUE to SELECT $alias.*, FALSE or NULL otherwise.
    * )
    *
    * @var array
@@ -356,6 +357,43 @@ class SelectQuery extends Query implemen
   }
 
   /**
+   * Add multiple fields from the same table to be SELECTed.
+   *
+   * This method does not return the aliases set for the passed fields.  In the
+   * majority of cases that is not a problem, as the alias will be the field
+   * name.  However, if you do need to know the alias you can call getFields()
+   * and examine the result to determine what alias was created.  Alternatively,
+   * simply use addField() for the few fields you care about and this method for
+   * the rest.
+   *
+   * @param $table_alias
+   *   The name of the table from which the field comes, as an alias.  Generally
+   *   you will want to use the return value of join() here to ensure that it is
+   *   valid.
+   * @param $fields
+   *   An indexed array of fields present in the specified table that should be
+   *   included in this query.  If not specified, $table_alias.* will be generated
+   *   without any aliases.
+   * @return
+   *   The called object.
+   */
+  public function fields($table_alias, Array $fields = array()) {
+
+    if ($fields) {
+      foreach ($fields as $field) {
+        // We don't care what alias was assigned.
+        $this->addField($table_alias, $field);
+      }
+    }
+    else {
+      // We want all fields from this table.
+      $this->tables[$table_alias]['all_fields'] = TRUE;
+    }
+
+    return $this;
+  }
+
+  /**
    * Adds an expression to the list of "fields" to be SELECTed.
    *
    * An expression can be any arbitrary string that is valid SQL.  That includes
@@ -633,8 +671,14 @@ class SelectQuery extends Query implemen
     foreach ($this->expressions as $alias => $expression) {
       $fields[] = $expression['expression'] . ' AS ' . $expression['alias'];
     }
+    foreach ($this->tables as $alias => $table) {
+      if (!empty($table['all_fields'])) {
+        $fields[] = $alias . '.*';
+      }
+    }
     $query .= implode(', ', $fields);
 
+
     // FROM - We presume all queries have a FROM, as any query that doesn't won't need the query builder anyway.
     $query .= "\nFROM ";
     foreach ($this->tables as $alias => $table) {
Index: modules/simpletest/tests/database_test.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.test,v
retrieving revision 1.10
diff -u -p -r1.10 database_test.test
--- modules/simpletest/tests/database_test.test	16 Oct 2008 14:58:48 -0000	1.10
+++ modules/simpletest/tests/database_test.test	18 Oct 2008 23:41:48 -0000
@@ -1009,6 +1009,54 @@ class DatabaseSelectTestCase extends Dat
     $this->assertEqual($record->$name_field, 'George', t('Fetched name is correct.'));
     $this->assertEqual($record->$age_field, 27*2, t('Fetched age expression is correct.'));
   }
+
+  /**
+   * Test adding multiple fields to a select statement at the same time.
+   */
+  function testSimpleSelectMultipleFields() {
+
+    $record = db_select('test')
+      ->fields('test', array('id', 'name', 'age', 'job'))
+      ->condition('age', 27)
+      ->execute()->fetchObject();
+
+    // Check that all fields we asked for are present.
+    $this->assertNotNull($record->id, t('ID field is present.'));
+    $this->assertNotNull($record->name, t('Name field is present.'));
+    $this->assertNotNull($record->age, t('Age field is present.'));
+    $this->assertNotNull($record->job, t('Job field is present.'));
+
+    // Ensure that we got the right record.
+    // Check that all fields we asked for are present.
+    $this->assertEqual($record->id, 2, t('ID field has the correct value.'));
+    $this->assertEqual($record->name, 'George', t('Name field has the correct value.'));
+    $this->assertEqual($record->age, 27, t('Age field has the correct value.'));
+    $this->assertEqual($record->job, 'Singer', t('Job field has the correct value.'));
+  }
+
+  /**
+   * Test adding all fields from a given table to a select statement.
+   */
+  function testSimpleSelectAllFields() {
+
+    $record = db_select('test')
+      ->fields('test')
+      ->condition('age', 27)
+      ->execute()->fetchObject();
+
+    // Check that all fields we asked for are present.
+    $this->assertNotNull($record->id, t('ID field is present.'));
+    $this->assertNotNull($record->name, t('Name field is present.'));
+    $this->assertNotNull($record->age, t('Age field is present.'));
+    $this->assertNotNull($record->job, t('Job field is present.'));
+
+    // Ensure that we got the right record.
+    // Check that all fields we asked for are present.
+    $this->assertEqual($record->id, 2, t('ID field has the correct value.'));
+    $this->assertEqual($record->name, 'George', t('Name field has the correct value.'));
+    $this->assertEqual($record->age, 27, t('Age field has the correct value.'));
+    $this->assertEqual($record->job, 'Singer', t('Job field has the correct value.'));
+  }
 }
 
 /**
@@ -1086,7 +1134,6 @@ class DatabaseSelectOrderedTestCase exte
     }
   }
 
-
   /**
    * Test order by descending.
    */
