diff --git includes/database/database.inc includes/database/database.inc
index 98dafae..38c9c55 100644
--- includes/database/database.inc
+++ includes/database/database.inc
@@ -785,6 +785,19 @@ abstract class DatabaseConnection extends PDO {
   }
 
   /**
+   * Prepares and returns a DatabaseCondition object for this database.
+   *
+   * @return DatabaseCondition
+   *   The DatabaseCondition object for this connection.
+   */
+  public function dbCondition($conjunction) {
+    $class = $this->getDriverClass('DatabaseCondition');
+    if (class_exists($class)) {
+      return new $class($conjunction);
+    }
+  }
+
+  /**
    * Escapes a table name string.
    *
    * Force all table names to be strictly alphanumeric-plus-underscore.
@@ -2538,7 +2551,7 @@ function db_next_id($existing_id = 0) {
  * @return DatabaseCondition
  */
 function db_or() {
-  return new DatabaseCondition('OR');
+  return Database::getConnection()->dbCondition('OR');
 }
 
 /**
@@ -2547,7 +2560,7 @@ function db_or() {
  * @return DatabaseCondition
  */
 function db_and() {
-  return new DatabaseCondition('AND');
+  return Database::getConnection()->dbCondition('AND');
 }
 
 /**
@@ -2556,7 +2569,7 @@ function db_and() {
  * @return DatabaseCondition
  */
 function db_xor() {
-  return new DatabaseCondition('XOR');
+  return Database::getConnection()->dbCondition('XOR');
 }
 
 /**
@@ -2570,7 +2583,7 @@ function db_xor() {
  * @return DatabaseCondition
  */
 function db_condition($conjunction) {
-  return new DatabaseCondition($conjunction);
+  return Database::getConnection()->dbCondition($conjunction);
 }
 
 /**
diff --git includes/database/mysql/query.inc includes/database/mysql/query.inc
index 584a4a4..942083f 100644
--- includes/database/mysql/query.inc
+++ includes/database/mysql/query.inc
@@ -103,6 +103,39 @@ class TruncateQuery_mysql extends TruncateQuery {
   }
 }
 
+
+class DatabaseCondition_mysql extends DatabaseCondition {
+
+  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder = NULL) {
+    if ($this->changed) {
+
+      // First preprocess the condition information to include extra
+      // wrapping layers for subselects. This is a MySQL-specific
+      // performance optimization, or rather a workaround for MySQL's
+      // rather poor handling of sub-selects.
+      // For more information on this technique see:
+      // http://www.xaprb.com/blog/2006/04/30/how-to-optimize-subqueries-and-joins-in-mysql/
+      foreach ($this->conditions as $key => $condition) {
+        if (isset($condition['value']) && $condition['value'] instanceof SelectQueryInterface) {
+          $inner_query = $condition['value'];
+          $wrapper = $connection->select($inner_query, 'inner_select_' . $queryPlaceholder->nextPlaceholder());
+          foreach (array_keys($inner_query->getFields()) as $alias) {
+            $wrapper->addExpression($alias, $alias);
+          }
+          foreach (array_keys($inner_query->getExpressions()) as $alias) {
+            $wrapper->addExpression($alias, $alias);
+          }
+          $this->conditions[$key]['value'] = $wrapper;
+        }
+      }
+    }
+
+    // Now compile the subselect as normal.
+    return parent::compile($connection, $queryPlaceholder);
+  }
+}
+
+
 /**
  * @} End of "ingroup database".
  */
diff --git includes/database/mysql/schema.inc includes/database/mysql/schema.inc
index ff1d99b..cbac700 100644
--- includes/database/mysql/schema.inc
+++ includes/database/mysql/schema.inc
@@ -60,7 +60,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
 
     $table_info = $this->getPrefixInfo($table_name, $add_prefix);
 
-    $condition = new DatabaseCondition('AND');
+    $condition = $this->connection->dbCondition('AND');
     $condition->condition('table_schema', $table_info['database']);
     $condition->condition('table_name', $table_info['table'], $operator);
     return $condition;
diff --git includes/database/query.inc includes/database/query.inc
index d7e688e..ae559f5 100644
--- includes/database/query.inc
+++ includes/database/query.inc
@@ -666,7 +666,7 @@ class DeleteQuery extends Query implements QueryConditionInterface {
     parent::__construct($connection, $options);
     $this->table = $table;
 
-    $this->condition = new DatabaseCondition('AND');
+    $this->condition = $this->connection->dbCondition('AND');
   }
 
   /**
@@ -886,7 +886,7 @@ class UpdateQuery extends Query implements QueryConditionInterface {
     parent::__construct($connection, $options);
     $this->table = $table;
 
-    $this->condition = new DatabaseCondition('AND');
+    $this->condition = $this->connection->dbCondition('AND');
   }
 
   /**
@@ -1183,7 +1183,7 @@ class MergeQuery extends Query implements QueryConditionInterface {
     parent::__construct($connection, $options);
     $this->table = $table;
     $this->conditionTable = $table;
-    $this->condition = new DatabaseCondition('AND');
+    $this->condition = $this->connection->dbCondition('AND');
   }
 
   /**
@@ -1644,9 +1644,13 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
 
             $placeholders = array();
             if ($condition['value'] instanceof SelectQueryInterface) {
-              $condition['value']->compile($connection, $queryPlaceholder);
+              // The order of commands here is taken from SelectQuery::execute(),
+              // as that's the proper way to ensure all of the preprocessing gets
+              // done appropriately.
+              $condition['value']->preExecute();
+              $arguments += $condition['value']->getArguments($queryPlaceholder);
               $placeholders[] = (string) $condition['value'];
-              $arguments += $condition['value']->arguments();
+
               // Subqueries are the actual value of the operator, we don't
               // need to add another below.
               $operator['use_value'] = FALSE;
diff --git includes/database/schema.inc includes/database/schema.inc
index 187f9e6..8d70aef 100644
--- includes/database/schema.inc
+++ includes/database/schema.inc
@@ -255,7 +255,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
     // Retrive the table name and schema
     $table_info = $this->getPrefixInfo($table_name, $add_prefix);
 
-    $condition = new DatabaseCondition('AND');
+    $condition = $this->connection->dbCondition('AND');
     $condition->condition('table_catalog', $info['database']);
     $condition->condition('table_schema', $table_info['schema']);
     $condition->condition('table_name', $table_info['table'], $operator);
diff --git includes/database/select.inc includes/database/select.inc
index 7780fc5..7136ffb 100644
--- includes/database/select.inc
+++ includes/database/select.inc
@@ -955,8 +955,8 @@ class SelectQuery extends Query implements SelectQueryInterface {
   public function __construct($table, $alias = NULL, DatabaseConnection $connection, $options = array()) {
     $options['return'] = Database::RETURN_STATEMENT;
     parent::__construct($connection, $options);
-    $this->where = new DatabaseCondition('AND');
-    $this->having = new DatabaseCondition('AND');
+    $this->where = $this->connection->dbCondition('AND');
+    $this->having = $this->connection->dbCondition('AND');
     $this->addJoin(NULL, $table, $alias);
   }
 
diff --git includes/database/sqlite/query.inc includes/database/sqlite/query.inc
index ec2b57a..935b570 100644
--- includes/database/sqlite/query.inc
+++ includes/database/sqlite/query.inc
@@ -103,7 +103,7 @@ class UpdateQuery_sqlite extends UpdateQuery {
     $this->removeFieldsInCondition($fields, $this->condition);
 
     // Add the inverse of the fields to the condition.
-    $condition = new DatabaseCondition('OR');
+    $condition = $this->connection->dbCondition('OR');
     foreach ($fields as $field => $data) {
       if (is_array($data)) {
         // The field is an expression.
