=== modified file 'includes/database/database.inc'
--- includes/database/database.inc	2008-11-08 04:45:36 +0000
+++ includes/database/database.inc	2008-11-08 19:47:33 +0000
@@ -155,6 +155,81 @@ abstract class DatabaseConnection extend
    */
   protected $logger = NULL;
 
+  /**
+   * Cache of prepared statements.
+   *
+   * This cache only lasts as long as the current page request, so it's not
+   * as useful as it could be, but every little bit helps.
+   *
+   * @var Array
+   */
+  protected $preparedStatements = array();
+
+  /**
+   * The name of the Select class for this connection.
+   *
+   * Normally this would be a static variable, but statics in methods are still
+   * global and shared by all instances.
+   *
+   * @var string
+   */
+  protected $selectClass = NULL;
+
+  /**
+   * The name of the Delete class for this connection.
+   *
+   * Normally this would be a static variable, but statics in methods are still
+   * global and shared by all instances.
+   *
+   * @var string
+   */
+  protected $deleteClass = NULL;
+
+  /**
+   * The name of the Insert class for this connection.
+   *
+   * Normally this would be a static variable, but statics in methods are still
+   * global and shared by all instances.
+   *
+   * @var string
+   */
+  protected $insertClass = NULL;
+
+  /**
+   * The name of the Merge class for this connection.
+   *
+   * Normally this would be a static variable, but statics in methods are still
+   * global and shared by all instances.
+   */
+  protected $mergeClass = NULL;
+
+  /**
+   * The name of the Update class for this connection.
+   *
+   * Normally this would be a static variable, but statics in methods are still
+   * global and shared by all instances.
+   *
+   * @var string
+   */
+  protected $updateClass = NULL;
+
+  /**
+   * The name of the Transaction class for this connection.
+   *
+   * Normally this would be a static variable, but statics in methods are still
+   * global and shared by all instances.
+   *
+   * @var string
+   */
+  protected $transactionClass = NULL;
+
+  /**
+   * The schema object for this connection.
+   *
+   * @var string
+   */
+  protected $schema = NULL;
+
   function __construct($dsn, $username, $password, $driver_options = array()) {
     // Because the other methods don't seem to work right.
     $driver_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
@@ -262,7 +337,7 @@ abstract class DatabaseConnection extend
   /**
    * Prepare a query string and return the prepared statement.
    *
-   * This method statically caches prepared statements, reusing them when
+   * This method caches prepared statements, reusing them when
    * possible.  It also prefixes tables names enclosed in curly-braces.
    *
    * @param $query
@@ -272,13 +347,12 @@ abstract class DatabaseConnection extend
    *   A PDO prepared statement ready for its execute() method.
    */
   protected function prepareQuery($query) {
-    static $statements = array();
     $query = self::prefixTables($query);
-    if (empty($statements[$query])) {
+    if (empty($this->preparedStatements[$query])) {
       // Call PDO::prepare.
-      $statements[$query] = parent::prepare($query);
+      $this->preparedStatements[$query] = parent::prepare($query);
     }
-    return $statements[$query];
+    return $this->preparedStatements[$query];
   }
 
   /**
@@ -352,8 +426,7 @@ abstract class DatabaseConnection extend
    *
    * This method provides a central handler for the actual execution
    * of every query.  All queries executed by Drupal are executed as
-   * PDO prepared statements.  This method statically caches those
-   * prepared statements, reusing them when possible.
+   * PDO prepared statements.
    *
    * @param $query
    *   The query to execute.  In most cases this will be a string containing
@@ -444,14 +517,18 @@ abstract class DatabaseConnection extend
    *   A new SelectQuery object.
    */
   public function select($table, $alias = NULL, Array $options = array()) {
-    static $class_type;
-    if (empty($class_type)) {
-      $class_type = 'SelectQuery_' . $this->driver();
-      if (!class_exists($class_type)) {
-        $class_type = 'SelectQuery';
+    if (empty($this->selectClass)) {
+      $this->selectClass = 'SelectQuery_' . $this->driver();
+      if (!class_exists($this->selectClass)) {
+        $this->selectClass = 'SelectQuery';
       }
     }
-    return new $class_type($table, $alias, $this, $options);
+    $class = $this->selectClass;
+    // new is documented as the highest precedence operator so this will
+    // create a class named $class and pass the arguments into the constructor,
+    // instead of calling a function named $class with the arguments listed and
+    // then creating using the return value as the class name.
+    return new $class($table, $alias, $this, $options);
   }
 
   /**
@@ -464,14 +541,14 @@ abstract class DatabaseConnection extend
    *   A new InsertQuery object.
    */
   public function insert($table, Array $options = array()) {
-    static $class_type;
-    if (empty($class_type)) {
-      $class_type = 'InsertQuery_' . $this->driver();
-      if (!class_exists($class_type)) {
-        $class_type = 'InsertQuery';
+    if (empty($this->insertClass)) {
+      $this->insertClass = 'InsertQuery_' . $this->driver();
+      if (!class_exists($this->insertClass)) {
+        $this->insertClass = 'InsertQuery';
       }
     }
-    return new $class_type($this, $table, $options);
+    $class = $this->insertClass;
+    return new $class($this, $table, $options);
   }
 
   /**
@@ -484,16 +561,17 @@ abstract class DatabaseConnection extend
    *   A new MergeQuery object.
    */
   public function merge($table, Array $options = array()) {
-    static $class_type;
-    if (empty($class_type)) {
-      $class_type = 'MergeQuery_' . $this->driver();
-      if (!class_exists($class_type)) {
-        $class_type = 'MergeQuery';
+    if (empty($this->mergeClass)) {
+      $this->mergeClass = 'MergeQuery_' . $this->driver();
+      if (!class_exists($this->mergeClass)) {
+        $this->mergeClass = 'MergeQuery';
       }
     }
-    return new $class_type($this, $table, $options);
+    $class = $this->mergeClass;
+    return new $class($this, $table, $options);
   }
 
+
   /**
    * Prepare and return an UPDATE query object with the specified ID.
    *
@@ -504,14 +582,14 @@ abstract class DatabaseConnection extend
    *   A new UpdateQuery object.
    */
   public function update($table, Array $options = array()) {
-    static $class_type;
-    if (empty($class_type)) {
-      $class_type = 'UpdateQuery_' . $this->driver();
-      if (!class_exists($class_type)) {
-        $class_type = 'UpdateQuery';
+    if (empty($this->updateClass)) {
+      $this->updateClass = 'UpdateQuery_' . $this->driver();
+      if (!class_exists($this->updateClass)) {
+        $this->updateClass = 'UpdateQuery';
       }
     }
-    return new $class_type($this, $table, $options);
+    $class = $this->updateClass;
+    return new $class($this, $table, $options);
   }
 
   /**
@@ -524,14 +602,14 @@ abstract class DatabaseConnection extend
    *   A new DeleteQuery object.
    */
   public function delete($table, Array $options = array()) {
-    static $class_type;
-    if (empty($class_type)) {
-      $class_type = 'DeleteQuery_' . $this->driver();
-      if (!class_exists($class_type)) {
-        $class_type = 'DeleteQuery';
+    if (empty($this->deleteClass)) {
+      $this->deleteClass = 'DeleteQuery_' . $this->driver();
+      if (!class_exists($this->deleteClass)) {
+        $this->deleteClass = 'DeleteQuery';
       }
     }
-    return new $class_type($this, $table, $options);
+    $class = $this->deleteClass
+    return new $class($this, $table, $options);
   }
 
   /**
@@ -543,12 +621,11 @@ abstract class DatabaseConnection extend
    *   The DatabaseSchema object for this connection.
    */
   public function schema() {
-    static $schema;
-    if (empty($schema)) {
+    if (empty($this->schema)) {
       $class_type = 'DatabaseSchema_' . $this->driver();
-      $schema = new $class_type($this);
+      $this->schema = new $class_type($this);
     }
-    return $schema;
+    return $this->schema;
   }
 
   /**
@@ -575,19 +652,17 @@ abstract class DatabaseConnection extend
    * @see DatabaseTransaction
    */
   public function startTransaction($required = FALSE) {
-    static $class_type;
-
     if ($required && !$this->supportsTransactions()) {
       throw new TransactionsNotSupportedException();
     }
 
-    if (empty($class_type)) {
-      $class_type = 'DatabaseTransaction_' . $this->driver();
-      if (!class_exists($class_type)) {
-        $class_type = 'DatabaseTransaction';
+    if (empty($this->transactionClass)) {
+      $this->transactionClass = 'DatabaseTransaction_' . $this->driver();
+      if (!class_exists($this->transactionClass)) {
+        $this->transactionClass = 'DatabaseTransaction';
       }
     }
-    return new $class_type($this);
+    return new $this->transactionClass($this);
   }
 
   /**

=== modified file 'includes/database/select.inc'
--- includes/database/select.inc	2008-10-29 09:40:17 +0000
+++ includes/database/select.inc	2008-11-08 19:37:53 +0000
@@ -401,6 +401,13 @@ class SelectQuery extends Query implemen
   }
 
   /**
+   * Private list of aliases already attributed to expression fields.
+   *
+   * @var Array
+   */
+  private $expressionAliases = array();
+
+  /**
    * Adds an expression to the list of "fields" to be SELECTed.
    *
    * An expression can be any arbitrary string that is valid SQL.  That includes
@@ -412,7 +419,7 @@ class SelectQuery extends Query implemen
    * @param $alias
    *   The alias for this expression.  If not specified, one will be generated
    *   automatically in the form "expression_#".  The alias will be checked for
-   *   uniqueness, so the requested alias may not be the alias that is asigned
+   *   uniqueness, so the requested alias may not be the alias that is assigned
    *   in all cases.
    * @param $arguments
    *   Any placeholder arguments needed for this expression.
@@ -420,19 +427,16 @@ class SelectQuery extends Query implemen
    *   The unique alias that was assigned for this expression.
    */
   public function addExpression($expression, $alias = NULL, $arguments = array()) {
-    static $alaises = array();
-
     if (empty($alias)) {
       $alias = 'expression';
     }
 
-    if (empty($aliases[$alias])) {
-      $aliases[$alias] = 1;
-    }
-
-    if (!empty($this->expressions[$alias])) {
-      $alias = $alias . '_' . $aliases[$alias]++;
+    $alias_candidate = $alias;
+    $count = 2;
+    while (!empty($this->expressions[$alias_candidate])) {
+      $alias_candidate = $alias . '_' . $count++;
     }
+    $alias = $alias_candidate;
 
     $this->expressions[$alias] = array(
       'expression' => $expression,

=== modified file 'modules/simpletest/tests/database_test.test'
--- modules/simpletest/tests/database_test.test	2008-11-08 07:06:03 +0000
+++ modules/simpletest/tests/database_test.test	2008-11-08 19:37:53 +0000
@@ -1044,6 +1044,28 @@ class DatabaseSelectTestCase extends Dat
   }
 
   /**
+   * Test SELECT statements with multiple expressions.
+   */
+  function testSimpleSelectExpressionMultiple() {
+    $query = db_select('test');
+    $name_field = $query->addField('test', 'name');
+    $age_double_field = $query->addExpression("age*2");
+    $age_triple_field = $query->addExpression("age*3");
+    $query->condition('age', 27);
+    $result = $query->execute();
+
+    // Check that the aliases are being created the way we want.
+    $this->assertEqual($age_double_field, 'expression', t('Double age field alias is correct.'));
+    $this->assertEqual($age_triple_field, 'expression_2', t('Triple age field alias is correct.'));
+
+    // Ensure that we got the right record.
+    $record = $result->fetch();
+    $this->assertEqual($record->$name_field, 'George', t('Fetched name is correct.'));
+    $this->assertEqual($record->$age_double_field, 27*2, t('Fetched double age expression is correct.'));
+    $this->assertEqual($record->$age_triple_field, 27*3, t('Fetched triple age expression is correct.'));
+  }
+
+  /**
    * Test adding multiple fields to a select statement at the same time.
    */
   function testSimpleSelectMultipleFields() {

