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. */