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:13:09 -0000
@@ -261,7 +261,8 @@ class SelectQuery extends Query implemen
   /**
    * Compiles and returns an associative array of the arguments for this prepared statement.
    *
-   * @return array
+   * @return
+   *   An associative array of all placeholder arguments for this query.
    */
   public function getArguments() {
     $this->where->compile($this->connection);
@@ -271,6 +272,10 @@ class SelectQuery extends Query implemen
       if ($table['arguments']) {
         $args += $table['arguments'];
       }
+      // If this table is a subquery, grab its arguments recursively.
+      if ($table['table'] instanceof SelectQuery) {
+        $args += $table['table']->getArguments();
+      }
     }
     foreach ($this->expressions as $expression) {
       if ($expression['arguments']) {
@@ -284,19 +289,7 @@ class SelectQuery extends Query implemen
   public function execute() {
     drupal_alter('query', $this);
 
-    $this->where->compile($this->connection);
-    $this->having->compile($this->connection);
-    $args = $this->where->arguments() + $this->having->arguments();
-    foreach ($this->tables as $table) {
-      if ($table['arguments']) {
-        $args += $table['arguments'];
-      }
-    }
-    foreach ($this->expressions as $expression) {
-      if ($expression['arguments']) {
-        $args += $expression['arguments'];
-      }
-    }
+    $args = $this->getArguments();
 
     if (!empty($this->range)) {
       return $this->connection->queryRange((string)$this, $args, $this->range['start'], $this->range['length'], $this->queryOptions);
@@ -499,8 +492,11 @@ class SelectQuery extends Query implemen
    * In some cases, that may include dipping into the Schema API to find the necessary
    * fields on which to join.
    *
+   * @param $type
+   *   The type of join.  Typically one one of INNER, LEFT OUTER, and RIGHT OUTER.
    * @param $table
-   *   The table against which to join.
+   *   The table against which to join.  May be a string or another SelectQuery
+   *   object.  If a query object is passed, it will be used as a subselect.
    * @param $alias
    *   The alias for the table.  In most cases this should be the first letter
    *   of the table, or the first letter of each "word" in the table.  If omitted,
@@ -519,7 +515,12 @@ class SelectQuery extends Query implemen
   public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array()) {
 
     if (empty($alias)) {
-      $alias = $table;
+      if ($table instanceof SelectQuery) {
+        $alias = 'subquery';
+      }
+      else {
+        $alias = $table;
+      }
     }
 
     $alias_candidate = $alias;
@@ -642,7 +643,16 @@ class SelectQuery extends Query implemen
       if (isset($table['join type'])) {
         $query .= $table['join type'] . ' JOIN ';
       }
-      $query .= '{' . $this->connection->escapeTable($table['table']) . '} AS ' . $table['alias'];
+
+      // If the table is a subquery, compile it and integrate it into this query.
+      if ($table['table'] instanceof SelectQuery) {
+        $table_string = '(' . (string)$table['table'] .')';
+      }
+      else {
+        $table_string = '{' .$this->connection->escapeTable($table['table']) . '}';
+      }
+
+      $query .=  $table_string . ' AS ' . $table['alias'];
       if (!empty($table['condition'])) {
         $query .= ' ON ' . $table['condition'];
       }
Index: modules/simpletest/tests/database_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.module,v
retrieving revision 1.2
diff -u -p -r1.2 database_test.module
--- modules/simpletest/tests/database_test.module	15 Sep 2008 20:48:09 -0000	1.2
+++ modules/simpletest/tests/database_test.module	18 Oct 2008 23:13:09 -0000
@@ -35,3 +35,4 @@ function database_test_query_alter(Selec
     $expressions['double_age']['expression'] = 'age*3';
   }
 }
+
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:13:09 -0000
@@ -1011,6 +1011,39 @@ class DatabaseSelectTestCase extends Dat
   }
 }
 
+class DatabaseSelectSubqueryTestCase extends DatabaseTestCase {
+
+  function getInfo() {
+    return array(
+      'name' => t('Select tests, subqueries'),
+      'description' => t('Test the Select query builder.'),
+      'group' => t('Database'),
+    );
+  }
+
+  /**
+   * Test rudimentary SELECT statements.
+   */
+  function testFromSubquerySelect() {
+    try {
+      $subquery = db_select('test_task', 'tt');
+      $subquery->addField('tt', 'pid', 'pid');
+      $subquery->condition('priority', 1);
+
+      $select = db_select('test', 't');
+      $select->join($subquery, 'tt', 't.id=tt.pid');
+      $select->addField('t', 'name');
+
+      $people = $select->execute()->fetchCol();
+
+      $this->assertEqual(count($people), 2, t('Returned the correct number of rows.'));
+    }
+    catch(Exception $e) {
+      $this->assertTrue(FALSE, $e->getMessage());
+    }
+  }
+}
+
 /**
  * Test select with order by clauses.
  */
