Index: includes/database/query.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/query.inc,v
retrieving revision 1.24
diff -u -p -r1.24 query.inc
--- includes/database/query.inc	5 Jun 2009 16:55:45 -0000	1.24
+++ includes/database/query.inc	7 Jun 2009 22:42:24 -0000
@@ -434,28 +434,16 @@ class InsertQuery extends Query {
    *   in multi-insert loops.
    */
   public function execute() {
-
-    $last_insert_id = 0;
-
-    // Check if a SelectQuery is passed in and use that.
-    if (!empty($this->fromQuery)) {
-      return $this->connection->query((string) $this, array(), $this->queryOptions);
-    }
-
-    // Confirm that the user did not try to specify an identical
-    //  field and default field.
-    if (array_intersect($this->insertFields, $this->defaultFields)) {
-      throw new PDOException('You may not specify the same field to have a value and a schema-default value.');
-    }
-
-    if (count($this->insertFields) + count($this->defaultFields) == 0) {
+    if (!$this->prepare()) {
       return NULL;
     }
 
-    // Don't execute query without values.
-    if (!isset($this->insertValues[0]) && count($this->insertFields) > 0) {
-      return NULL;
+    // Check if a SelectQuery is passed in and use that.
+    if (!empty($this->fromQuery)) {
+      return $this->connection->query((string)$this, $this->fromQuery->getArguments(), $this->queryOptions);
     }
+    
+    $last_insert_id = 0;
 
     // Each insert happens in its own query in the degenerate case. However,
     // we wrap it in a transaction so that it is atomic where possible. On many
@@ -492,6 +480,37 @@ class InsertQuery extends Query {
 
     return 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES (' . implode(', ', $placeholders) . ')';
   }
+
+  /**
+   * Generic preparation and validation for an INSERT query.
+   *
+   * @return
+   *   TRUE if the validation was successful, FALSE if not.
+   */
+  protected function prepare() {
+    // Confirm that the user did not try to specify an identical
+    // field and default field.
+    if (array_intersect($this->insertFields, $this->defaultFields)) {
+      throw new PDOException('You may not specify the same field to have a value and a schema-default value.');
+    }
+
+    if (!empty($this->fromQuery)) {
+      // Use the defined aliases for the INSERT query fields.
+      // Fields are added before expressions in __toString().
+      $this->fields(array_merge(array_keys($this->fromQuery->getFields()), array_keys($this->fromQuery->getExpressions())));
+    }
+
+    // Don't execute query without fields.
+    if (count($this->insertFields) + count($this->defaultFields) == 0) {
+      return FALSE;
+    }
+
+    // Don't execute query without values.
+    if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
+      return FALSE;
+    }
+    return TRUE;
+  }
 }
 
 /**
Index: includes/database/mysql/query.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/mysql/query.inc,v
retrieving revision 1.12
diff -u -p -r1.12 query.inc
--- includes/database/mysql/query.inc	5 Jun 2009 16:55:45 -0000	1.12
+++ includes/database/mysql/query.inc	7 Jun 2009 22:42:25 -0000
@@ -15,19 +15,7 @@
 class InsertQuery_mysql extends InsertQuery {
 
   public function execute() {
-
-    // Confirm that the user did not try to specify an identical
-    //  field and default field.
-    if (array_intersect($this->insertFields, $this->defaultFields)) {
-      throw new PDOException('You may not specify the same field to have a value and a schema-default value.');
-    }
-
-    if (count($this->insertFields) + count($this->defaultFields) == 0 && empty($this->fromQuery)) {
-      return NULL;
-    }
-
-    // Don't execute query without values.
-    if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
+    if (!$this->prepare()) {
       return NULL;
     }
 
@@ -41,6 +29,10 @@ class InsertQuery_mysql extends InsertQu
       }
     }
 
+    if (!empty($this->fromQuery)) {
+      $values += $this->fromQuery->getArguments();
+    }
+
     $last_insert_id = $this->connection->query((string)$this, $values, $this->queryOptions);
 
     // Re-initialize the values array so that we can re-use this query.
Index: includes/database/pgsql/query.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/pgsql/query.inc,v
retrieving revision 1.13
diff -u -p -r1.13 query.inc
--- includes/database/pgsql/query.inc	5 Jun 2009 16:55:45 -0000	1.13
+++ includes/database/pgsql/query.inc	7 Jun 2009 22:42:25 -0000
@@ -15,19 +15,7 @@
 class InsertQuery_pgsql extends InsertQuery {
 
   public function execute() {
-
-    // Confirm that the user did not try to specify an identical
-    //  field and default field.
-    if (array_intersect($this->insertFields, $this->defaultFields)) {
-      throw new PDOException('You may not specify the same field to have a value and a schema-default value.');
-    }
-
-    if (count($this->insertFields) + count($this->defaultFields) == 0 && empty($this->fromQuery)) {
-      return NULL;
-    }
-
-    // Don't execute query without values.
-    if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
+    if (!$this->prepare()) {
       return NULL;
     }
 
@@ -56,6 +44,11 @@ class InsertQuery_pgsql extends InsertQu
         }
       }
     }
+    if (!empty($this->fromQuery)) {
+      foreach ($this->fromQuery->getArguments() as $key => $value) {
+        $stmt->bindParam($key, $value);
+      }
+    }
 
     // PostgreSQL requires the table name to be specified explicitly
     // when requesting the last insert ID, so we pass that in via
Index: includes/database/sqlite/query.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/sqlite/query.inc,v
retrieving revision 1.6
diff -u -p -r1.6 query.inc
--- includes/database/sqlite/query.inc	5 Jun 2009 16:55:45 -0000	1.6
+++ includes/database/sqlite/query.inc	7 Jun 2009 22:42:25 -0000
@@ -21,11 +21,7 @@
 class InsertQuery_sqlite extends InsertQuery {
 
   public function execute() {
-    if (count($this->insertFields) + count($this->defaultFields) == 0 && empty($this->fromQuery)) {
-      return NULL;
-    }
-    // Don't execute query without values.
-    if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
+    if (!$this->prepare()) {
       return NULL;
     }
     if (count($this->insertFields)) {
Index: modules/simpletest/tests/database_test.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.test,v
retrieving revision 1.57
diff -u -p -r1.57 database_test.test
--- modules/simpletest/tests/database_test.test	5 Jun 2009 16:55:45 -0000	1.57
+++ modules/simpletest/tests/database_test.test	7 Jun 2009 22:42:27 -0000
@@ -518,10 +518,14 @@ class DatabaseInsertTestCase extends Dat
    * Test that the INSERT INTO ... SELECT ... syntax works.
    */
   function testInsertSelect() {
-    $query = db_select('test_people', 'tp')->fields('tp', array('name', 'age', 'job'));
+    $query = db_select('test_people', 'tp');
+    // Use an expression to test the correct order of the insert query fields.
+    $query->addExpression('tp.age', 'age');
+    $query
+      ->fields('tp', array('name','job'))
+      ->condition('tp.name', 'Meredith');
 
     db_insert('test')
-      ->fields(array('name', 'age', 'job'))
       ->from($query)
       ->execute();
 
