diff --git a/core/MAINTAINERS.txt b/core/MAINTAINERS.txt
index 564cffa716c7144d9e13bd9310ecc079bf3c2710..3a7c6077c91a9a30fe07d8b4f8f322d4304b5342 100644
--- a/core/MAINTAINERS.txt
+++ b/core/MAINTAINERS.txt
@@ -174,7 +174,7 @@ Contextual module
 Dashboard module
 - ?
 
-Database logging module
+Database Logging module
 - Khalid Baheyeldin 'kbahey' <http://drupal.org/user/4063>
 
 Field module
diff --git a/core/includes/ajax.inc b/core/includes/ajax.inc
index 8683ff9df73e0cdbbd74290ef0797cceb7bab1b7..8817356d1822064e0a3ec4fc8a58ed9dd18dc85c 100644
--- a/core/includes/ajax.inc
+++ b/core/includes/ajax.inc
@@ -351,8 +351,6 @@ function ajax_get_form() {
 /**
  * Page callback: Handles Ajax requests for the #ajax Form API property.
  *
- * Path: system/ajax
- *
  * This rebuilds the form from cache and invokes the defined #ajax['callback']
  * to return an Ajax command structure for JavaScript. In case no 'callback' has
  * been defined, nothing will happen.
@@ -388,11 +386,6 @@ function ajax_form_callback() {
 /**
  * Theme callback: Returns the correct theme for an Ajax request.
  *
- * Paths:
- *   - system/ajax
- *   - file/ajax
- *   - file/progress
- *
  * Many different pages can invoke an Ajax request to system/ajax or another
  * generic Ajax path. It is almost always desired for an Ajax response to be
  * rendered using the same theme as the base page, because most themes are built
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 30e3c3b8091c1df299edbb87ce59ccdc320df7bf..a7002355768279bb2bca7a4064c2a18544d0fe98 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1,5 +1,6 @@
 <?php
 
+use Drupal\Core\Database\Database;
 use Symfony\Component\ClassLoader\UniversalClassLoader;
 use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
 
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 6d1c44b7c897ddc7cf538a54734d54fec00889a3..38520acdb29d374a99f5caad8ca6070df9b611ce 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * @file
  * Common functions that many Drupal modules will need to reference.
diff --git a/core/includes/database/database.inc b/core/includes/database/database.inc
index 7c96e070b006504551fd2373ed269b71703bdff7..c2df94988ffd6602810cb96ca3623a9d8deab81e 100644
--- a/core/includes/database/database.inc
+++ b/core/includes/database/database.inc
@@ -1,5 +1,8 @@
 <?php
 
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Query\Condition;
+
 /**
  * @file
  * Core systems for the database layer.
@@ -171,2109 +174,6 @@
  */
 
 
-/**
- * Base Database API class.
- *
- * This class provides a Drupal-specific extension of the PDO database
- * abstraction class in PHP. Every database driver implementation must provide a
- * concrete implementation of it to support special handling required by that
- * database.
- *
- * @see http://php.net/manual/en/book.pdo.php
- */
-abstract class DatabaseConnection extends PDO {
-
-  /**
-   * The database target this connection is for.
-   *
-   * We need this information for later auditing and logging.
-   *
-   * @var string
-   */
-  protected $target = NULL;
-
-  /**
-   * The key representing this connection.
-   *
-   * The key is a unique string which identifies a database connection. A
-   * connection can be a single server or a cluster of master and slaves (use
-   * target to pick between master and slave).
-   *
-   * @var string
-   */
-  protected $key = NULL;
-
-  /**
-   * The current database logging object for this connection.
-   *
-   * @var DatabaseLog
-   */
-  protected $logger = NULL;
-
-  /**
-   * Tracks the number of "layers" of transactions currently active.
-   *
-   * On many databases transactions cannot nest.  Instead, we track
-   * nested calls to transactions and collapse them into a single
-   * transaction.
-   *
-   * @var array
-   */
-  protected $transactionLayers = array();
-
-  /**
-   * Index of what driver-specific class to use for various operations.
-   *
-   * @var array
-   */
-  protected $driverClasses = array();
-
-  /**
-   * The name of the Statement class for this connection.
-   *
-   * @var string
-   */
-  protected $statementClass = 'DatabaseStatementBase';
-
-  /**
-   * Whether this database connection supports transactions.
-   *
-   * @var bool
-   */
-  protected $transactionSupport = TRUE;
-
-  /**
-   * Whether this database connection supports transactional DDL.
-   *
-   * Set to FALSE by default because few databases support this feature.
-   *
-   * @var bool
-   */
-  protected $transactionalDDLSupport = FALSE;
-
-  /**
-   * An index used to generate unique temporary table names.
-   *
-   * @var integer
-   */
-  protected $temporaryNameIndex = 0;
-
-  /**
-   * The connection information for this connection object.
-   *
-   * @var array
-   */
-  protected $connectionOptions = array();
-
-  /**
-   * The schema object for this connection.
-   *
-   * @var object
-   */
-  protected $schema = NULL;
-
-  /**
-   * The prefixes used by this database connection.
-   *
-   * @var array
-   */
-  protected $prefixes = array();
-
-  /**
-   * List of search values for use in prefixTables().
-   *
-   * @var array
-   */
-  protected $prefixSearch = array();
-
-  /**
-   * List of replacement values for use in prefixTables().
-   *
-   * @var array
-   */
-  protected $prefixReplace = array();
-
-  function __construct($dsn, $username, $password, $driver_options = array()) {
-    // Initialize and prepare the connection prefix.
-    $this->setPrefix(isset($this->connectionOptions['prefix']) ? $this->connectionOptions['prefix'] : '');
-
-    // Because the other methods don't seem to work right.
-    $driver_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
-
-    // Call PDO::__construct and PDO::setAttribute.
-    parent::__construct($dsn, $username, $password, $driver_options);
-
-    // Set a specific PDOStatement class if the driver requires that.
-    if (!empty($this->statementClass)) {
-      $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this)));
-    }
-  }
-
-  /**
-   * Returns the default query options for any given query.
-   *
-   * A given query can be customized with a number of option flags in an
-   * associative array:
-   * - target: The database "target" against which to execute a query. Valid
-   *   values are "default" or "slave". The system will first try to open a
-   *   connection to a database specified with the user-supplied key. If one
-   *   is not available, it will silently fall back to the "default" target.
-   *   If multiple databases connections are specified with the same target,
-   *   one will be selected at random for the duration of the request.
-   * - fetch: This element controls how rows from a result set will be
-   *   returned. Legal values include PDO::FETCH_ASSOC, PDO::FETCH_BOTH,
-   *   PDO::FETCH_OBJ, PDO::FETCH_NUM, or a string representing the name of a
-   *   class. If a string is specified, each record will be fetched into a new
-   *   object of that class. The behavior of all other values is defined by PDO.
-   *   See http://php.net/manual/pdostatement.fetch.php
-   * - return: Depending on the type of query, different return values may be
-   *   meaningful. This directive instructs the system which type of return
-   *   value is desired. The system will generally set the correct value
-   *   automatically, so it is extremely rare that a module developer will ever
-   *   need to specify this value. Setting it incorrectly will likely lead to
-   *   unpredictable results or fatal errors. Legal values include:
-   *   - Database::RETURN_STATEMENT: Return the prepared statement object for
-   *     the query. This is usually only meaningful for SELECT queries, where
-   *     the statement object is how one accesses the result set returned by the
-   *     query.
-   *   - Database::RETURN_AFFECTED: Return the number of rows affected by an
-   *     UPDATE or DELETE query. Be aware that means the number of rows actually
-   *     changed, not the number of rows matched by the WHERE clause.
-   *   - Database::RETURN_INSERT_ID: Return the sequence ID (primary key)
-   *     created by an INSERT statement on a table that contains a serial
-   *     column.
-   *   - Database::RETURN_NULL: Do not return anything, as there is no
-   *     meaningful value to return. That is the case for INSERT queries on
-   *     tables that do not contain a serial column.
-   * - throw_exception: By default, the database system will catch any errors
-   *   on a query as an Exception, log it, and then rethrow it so that code
-   *   further up the call chain can take an appropriate action. To suppress
-   *   that behavior and simply return NULL on failure, set this option to
-   *   FALSE.
-   *
-   * @return
-   *   An array of default query options.
-   */
-  protected function defaultOptions() {
-    return array(
-      'target' => 'default',
-      'fetch' => PDO::FETCH_OBJ,
-      'return' => Database::RETURN_STATEMENT,
-      'throw_exception' => TRUE,
-    );
-  }
-
-  /**
-   * Returns the connection information for this connection object.
-   *
-   * Note that Database::getConnectionInfo() is for requesting information
-   * about an arbitrary database connection that is defined. This method
-   * is for requesting the connection information of this specific
-   * open connection object.
-   *
-   * @return
-   *   An array of the connection information. The exact list of
-   *   properties is driver-dependent.
-   */
-  public function getConnectionOptions() {
-    return $this->connectionOptions;
-  }
-
-  /**
-   * Set the list of prefixes used by this database connection.
-   *
-   * @param $prefix
-   *   The prefixes, in any of the multiple forms documented in
-   *   default.settings.php.
-   */
-  protected function setPrefix($prefix) {
-    if (is_array($prefix)) {
-      $this->prefixes = $prefix + array('default' => '');
-    }
-    else {
-      $this->prefixes = array('default' => $prefix);
-    }
-
-    // Set up variables for use in prefixTables(). Replace table-specific
-    // prefixes first.
-    $this->prefixSearch = array();
-    $this->prefixReplace = array();
-    foreach ($this->prefixes as $key => $val) {
-      if ($key != 'default') {
-        $this->prefixSearch[] = '{' . $key . '}';
-        $this->prefixReplace[] = $val . $key;
-      }
-    }
-    // Then replace remaining tables with the default prefix.
-    $this->prefixSearch[] = '{';
-    $this->prefixReplace[] = $this->prefixes['default'];
-    $this->prefixSearch[] = '}';
-    $this->prefixReplace[] = '';
-  }
-
-  /**
-   * Appends a database prefix to all tables in a query.
-   *
-   * Queries sent to Drupal should wrap all table names in curly brackets. This
-   * function searches for this syntax and adds Drupal's table prefix to all
-   * tables, allowing Drupal to coexist with other systems in the same database
-   * and/or schema if necessary.
-   *
-   * @param $sql
-   *   A string containing a partial or entire SQL query.
-   *
-   * @return
-   *   The properly-prefixed string.
-   */
-  public function prefixTables($sql) {
-    return str_replace($this->prefixSearch, $this->prefixReplace, $sql);
-  }
-
-  /**
-   * Find the prefix for a table.
-   *
-   * This function is for when you want to know the prefix of a table. This
-   * is not used in prefixTables due to performance reasons.
-   */
-  public function tablePrefix($table = 'default') {
-    if (isset($this->prefixes[$table])) {
-      return $this->prefixes[$table];
-    }
-    else {
-      return $this->prefixes['default'];
-    }
-  }
-
-  /**
-   * Prepares a query string and returns the prepared statement.
-   *
-   * This method caches prepared statements, reusing them when
-   * possible. It also prefixes tables names enclosed in curly-braces.
-   *
-   * @param $query
-   *   The query string as SQL, with curly-braces surrounding the
-   *   table names.
-   *
-   * @return DatabaseStatementInterface
-   *   A PDO prepared statement ready for its execute() method.
-   */
-  public function prepareQuery($query) {
-    $query = $this->prefixTables($query);
-
-    // Call PDO::prepare.
-    return parent::prepare($query);
-  }
-
-  /**
-   * Tells this connection object what its target value is.
-   *
-   * This is needed for logging and auditing. It's sloppy to do in the
-   * constructor because the constructor for child classes has a different
-   * signature. We therefore also ensure that this function is only ever
-   * called once.
-   *
-   * @param $target
-   *   The target this connection is for. Set to NULL (default) to disable
-   *   logging entirely.
-   */
-  public function setTarget($target = NULL) {
-    if (!isset($this->target)) {
-      $this->target = $target;
-    }
-  }
-
-  /**
-   * Returns the target this connection is associated with.
-   *
-   * @return
-   *   The target string of this connection.
-   */
-  public function getTarget() {
-    return $this->target;
-  }
-
-  /**
-   * Tells this connection object what its key is.
-   *
-   * @param $target
-   *   The key this connection is for.
-   */
-  public function setKey($key) {
-    if (!isset($this->key)) {
-      $this->key = $key;
-    }
-  }
-
-  /**
-   * Returns the key this connection is associated with.
-   *
-   * @return
-   *   The key of this connection.
-   */
-  public function getKey() {
-    return $this->key;
-  }
-
-  /**
-   * Associates a logging object with this connection.
-   *
-   * @param $logger
-   *   The logging object we want to use.
-   */
-  public function setLogger(DatabaseLog $logger) {
-    $this->logger = $logger;
-  }
-
-  /**
-   * Gets the current logging object for this connection.
-   *
-   * @return DatabaseLog
-   *   The current logging object for this connection. If there isn't one,
-   *   NULL is returned.
-   */
-  public function getLogger() {
-    return $this->logger;
-  }
-
-  /**
-   * Creates the appropriate sequence name for a given table and serial field.
-   *
-   * This information is exposed to all database drivers, although it is only
-   * useful on some of them. This method is table prefix-aware.
-   *
-   * @param $table
-   *   The table name to use for the sequence.
-   * @param $field
-   *   The field name to use for the sequence.
-   *
-   * @return
-   *   A table prefix-parsed string for the sequence name.
-   */
-  public function makeSequenceName($table, $field) {
-    return $this->prefixTables('{' . $table . '}_' . $field . '_seq');
-  }
-
-  /**
-   * Flatten an array of query comments into a single comment string.
-   *
-   * The comment string will be sanitized to avoid SQL injection attacks.
-   *
-   * @param $comments
-   *   An array of query comment strings.
-   *
-   * @return
-   *   A sanitized comment string.
-   */
-  public function makeComment($comments) {
-    if (empty($comments))
-      return '';
-
-    // Flatten the array of comments.
-    $comment = implode('; ', $comments);
-
-    // Sanitize the comment string so as to avoid SQL injection attacks.
-    return '/* ' . $this->filterComment($comment) . ' */ ';
-  }
-
-  /**
-   * Sanitize a query comment string.
-   *
-   * Ensure a query comment does not include strings such as "* /" that might
-   * terminate the comment early. This avoids SQL injection attacks via the
-   * query comment. The comment strings in this example are separated by a
-   * space to avoid PHP parse errors.
-   *
-   * For example, the comment:
-   * @code
-   * db_update('example')
-   *  ->condition('id', $id)
-   *  ->fields(array('field2' => 10))
-   *  ->comment('Exploit * / DROP TABLE node; --')
-   *  ->execute()
-   * @endcode
-   *
-   * Would result in the following SQL statement being generated:
-   * @code
-   * "/ * Exploit * / DROP TABLE node; -- * / UPDATE example SET field2=..."
-   * @endcode
-   *
-   * Unless the comment is sanitised first, the SQL server would drop the
-   * node table and ignore the rest of the SQL statement.
-   *
-   * @param $comment
-   *   A query comment string.
-   *
-   * @return
-   *   A sanitized version of the query comment string.
-   */
-  protected function filterComment($comment = '') {
-    return preg_replace('/(\/\*\s*)|(\s*\*\/)/', '', $comment);
-  }
-
-  /**
-   * Executes a query string against the database.
-   *
-   * This method provides a central handler for the actual execution of every
-   * query. All queries executed by Drupal are executed as PDO prepared
-   * statements.
-   *
-   * @param $query
-   *   The query to execute. In most cases this will be a string containing
-   *   an SQL query with placeholders. An already-prepared instance of
-   *   DatabaseStatementInterface may also be passed in order to allow calling
-   *   code to manually bind variables to a query. If a
-   *   DatabaseStatementInterface is passed, the $args array will be ignored.
-   *   It is extremely rare that module code will need to pass a statement
-   *   object to this method. It is used primarily for database drivers for
-   *   databases that require special LOB field handling.
-   * @param $args
-   *   An array of arguments for the prepared statement. If the prepared
-   *   statement uses ? placeholders, this array must be an indexed array.
-   *   If it contains named placeholders, it must be an associative array.
-   * @param $options
-   *   An associative array of options to control how the query is run. See
-   *   the documentation for DatabaseConnection::defaultOptions() for details.
-   *
-   * @return DatabaseStatementInterface
-   *   This method will return one of: the executed statement, the number of
-   *   rows affected by the query (not the number matched), or the generated
-   *   insert IT of the last query, depending on the value of
-   *   $options['return']. Typically that value will be set by default or a
-   *   query builder and should not be set by a user. If there is an error,
-   *   this method will return NULL and may throw an exception if
-   *   $options['throw_exception'] is TRUE.
-   *
-   * @throws PDOException
-   */
-  public function query($query, array $args = array(), $options = array()) {
-
-    // Use default values if not already set.
-    $options += $this->defaultOptions();
-
-    try {
-      // We allow either a pre-bound statement object or a literal string.
-      // In either case, we want to end up with an executed statement object,
-      // which we pass to PDOStatement::execute.
-      if ($query instanceof DatabaseStatementInterface) {
-        $stmt = $query;
-        $stmt->execute(NULL, $options);
-      }
-      else {
-        $this->expandArguments($query, $args);
-        $stmt = $this->prepareQuery($query);
-        $stmt->execute($args, $options);
-      }
-
-      // Depending on the type of query we may need to return a different value.
-      // See DatabaseConnection::defaultOptions() for a description of each
-      // value.
-      switch ($options['return']) {
-        case Database::RETURN_STATEMENT:
-          return $stmt;
-        case Database::RETURN_AFFECTED:
-          return $stmt->rowCount();
-        case Database::RETURN_INSERT_ID:
-          return $this->lastInsertId();
-        case Database::RETURN_NULL:
-          return;
-        default:
-          throw new PDOException('Invalid return directive: ' . $options['return']);
-      }
-    }
-    catch (PDOException $e) {
-      if ($options['throw_exception']) {
-        // Add additional debug information.
-        if ($query instanceof DatabaseStatementInterface) {
-          $e->query_string = $stmt->getQueryString();
-        }
-        else {
-          $e->query_string = $query;
-        }
-        $e->args = $args;
-        throw $e;
-      }
-      return NULL;
-    }
-  }
-
-  /**
-   * Expands out shorthand placeholders.
-   *
-   * Drupal supports an alternate syntax for doing arrays of values. We
-   * therefore need to expand them out into a full, executable query string.
-   *
-   * @param $query
-   *   The query string to modify.
-   * @param $args
-   *   The arguments for the query.
-   *
-   * @return
-   *   TRUE if the query was modified, FALSE otherwise.
-   */
-  protected function expandArguments(&$query, &$args) {
-    $modified = FALSE;
-
-    // If the placeholder value to insert is an array, assume that we need
-    // to expand it out into a comma-delimited set of placeholders.
-    foreach (array_filter($args, 'is_array') as $key => $data) {
-      $new_keys = array();
-      foreach ($data as $i => $value) {
-        // This assumes that there are no other placeholders that use the same
-        // name.  For example, if the array placeholder is defined as :example
-        // and there is already an :example_2 placeholder, this will generate
-        // a duplicate key.  We do not account for that as the calling code
-        // is already broken if that happens.
-        $new_keys[$key . '_' . $i] = $value;
-      }
-
-      // Update the query with the new placeholders.
-      // preg_replace is necessary to ensure the replacement does not affect
-      // placeholders that start with the same exact text. For example, if the
-      // query contains the placeholders :foo and :foobar, and :foo has an
-      // array of values, using str_replace would affect both placeholders,
-      // but using the following preg_replace would only affect :foo because
-      // it is followed by a non-word character.
-      $query = preg_replace('#' . $key . '\b#', implode(', ', array_keys($new_keys)), $query);
-
-      // Update the args array with the new placeholders.
-      unset($args[$key]);
-      $args += $new_keys;
-
-      $modified = TRUE;
-    }
-
-    return $modified;
-  }
-
-  /**
-   * Gets the driver-specific override class if any for the specified class.
-   *
-   * @param string $class
-   *   The class for which we want the potentially driver-specific class.
-   * @param array $files
-   *   The name of the files in which the driver-specific class can be.
-   * @param $use_autoload
-   *   If TRUE, attempt to load classes using PHP's autoload capability
-   *   as well as the manual approach here.
-   * @return string
-   *   The name of the class that should be used for this driver.
-   */
-  public function getDriverClass($class, array $files = array(), $use_autoload = FALSE) {
-    if (empty($this->driverClasses[$class])) {
-      $driver = $this->driver();
-      $this->driverClasses[$class] = $class . '_' . $driver;
-      Database::loadDriverFile($driver, $files);
-      if (!class_exists($this->driverClasses[$class], $use_autoload)) {
-        $this->driverClasses[$class] = $class;
-      }
-    }
-    return $this->driverClasses[$class];
-  }
-
-  /**
-   * Prepares and returns a SELECT query object.
-   *
-   * @param $table
-   *   The base table for this query, that is, the first table in the FROM
-   *   clause. This table will also be used as the "base" table for query_alter
-   *   hook implementations.
-   * @param $alias
-   *   The alias of the base table of this query.
-   * @param $options
-   *   An array of options on the query.
-   *
-   * @return SelectQueryInterface
-   *   An appropriate SelectQuery object for this database connection. Note that
-   *   it may be a driver-specific subclass of SelectQuery, depending on the
-   *   driver.
-   *
-   * @see SelectQuery
-   */
-  public function select($table, $alias = NULL, array $options = array()) {
-    $class = $this->getDriverClass('SelectQuery', array('query.inc', 'select.inc'));
-    return new $class($table, $alias, $this, $options);
-  }
-
-  /**
-   * Prepares and returns an INSERT query object.
-   *
-   * @param $options
-   *   An array of options on the query.
-   *
-   * @return InsertQuery
-   *   A new InsertQuery object.
-   *
-   * @see InsertQuery
-   */
-  public function insert($table, array $options = array()) {
-    $class = $this->getDriverClass('InsertQuery', array('query.inc'));
-    return new $class($this, $table, $options);
-  }
-
-  /**
-   * Prepares and returns a MERGE query object.
-   *
-   * @param $options
-   *   An array of options on the query.
-   *
-   * @return MergeQuery
-   *   A new MergeQuery object.
-   *
-   * @see MergeQuery
-   */
-  public function merge($table, array $options = array()) {
-    $class = $this->getDriverClass('MergeQuery', array('query.inc'));
-    return new $class($this, $table, $options);
-  }
-
-
-  /**
-   * Prepares and returns an UPDATE query object.
-   *
-   * @param $options
-   *   An array of options on the query.
-   *
-   * @return UpdateQuery
-   *   A new UpdateQuery object.
-   *
-   * @see UpdateQuery
-   */
-  public function update($table, array $options = array()) {
-    $class = $this->getDriverClass('UpdateQuery', array('query.inc'));
-    return new $class($this, $table, $options);
-  }
-
-  /**
-   * Prepares and returns a DELETE query object.
-   *
-   * @param $options
-   *   An array of options on the query.
-   *
-   * @return DeleteQuery
-   *   A new DeleteQuery object.
-   *
-   * @see DeleteQuery
-   */
-  public function delete($table, array $options = array()) {
-    $class = $this->getDriverClass('DeleteQuery', array('query.inc'));
-    return new $class($this, $table, $options);
-  }
-
-  /**
-   * Prepares and returns a TRUNCATE query object.
-   *
-   * @param $options
-   *   An array of options on the query.
-   *
-   * @return TruncateQuery
-   *   A new TruncateQuery object.
-   *
-   * @see TruncateQuery
-   */
-  public function truncate($table, array $options = array()) {
-    $class = $this->getDriverClass('TruncateQuery', array('query.inc'));
-    return new $class($this, $table, $options);
-  }
-
-  /**
-   * Returns a DatabaseSchema object for manipulating the schema.
-   *
-   * This method will lazy-load the appropriate schema library file.
-   *
-   * @return DatabaseSchema
-   *   The DatabaseSchema object for this connection.
-   */
-  public function schema() {
-    if (empty($this->schema)) {
-      $class = $this->getDriverClass('DatabaseSchema', array('schema.inc'));
-      if (class_exists($class)) {
-        $this->schema = new $class($this);
-      }
-    }
-    return $this->schema;
-  }
-
-  /**
-   * Escapes a table name string.
-   *
-   * Force all table names to be strictly alphanumeric-plus-underscore.
-   * For some database drivers, it may also wrap the table name in
-   * database-specific escape characters.
-   *
-   * @return
-   *   The sanitized table name string.
-   */
-  public function escapeTable($table) {
-    return preg_replace('/[^A-Za-z0-9_.]+/', '', $table);
-  }
-
-  /**
-   * Escapes a field name string.
-   *
-   * Force all field names to be strictly alphanumeric-plus-underscore.
-   * For some database drivers, it may also wrap the field name in
-   * database-specific escape characters.
-   *
-   * @return
-   *   The sanitized field name string.
-   */
-  public function escapeField($field) {
-    return preg_replace('/[^A-Za-z0-9_.]+/', '', $field);
-  }
-
-  /**
-   * Escapes an alias name string.
-   *
-   * Force all alias names to be strictly alphanumeric-plus-underscore. In
-   * contrast to DatabaseConnection::escapeField() /
-   * DatabaseConnection::escapeTable(), this doesn't allow the period (".")
-   * because that is not allowed in aliases.
-   *
-   * @return
-   *   The sanitized field name string.
-   */
-  public function escapeAlias($field) {
-    return preg_replace('/[^A-Za-z0-9_]+/', '', $field);
-  }
-
-  /**
-   * Escapes characters that work as wildcard characters in a LIKE pattern.
-   *
-   * The wildcard characters "%" and "_" as well as backslash are prefixed with
-   * a backslash. Use this to do a search for a verbatim string without any
-   * wildcard behavior.
-   *
-   * For example, the following does a case-insensitive query for all rows whose
-   * name starts with $prefix:
-   * @code
-   * $result = db_query(
-   *   'SELECT * FROM person WHERE name LIKE :pattern',
-   *   array(':pattern' => db_like($prefix) . '%')
-   * );
-   * @endcode
-   *
-   * Backslash is defined as escape character for LIKE patterns in
-   * DatabaseCondition::mapConditionOperator().
-   *
-   * @param $string
-   *   The string to escape.
-   *
-   * @return
-   *   The escaped string.
-   */
-  public function escapeLike($string) {
-    return addcslashes($string, '\%_');
-  }
-
-  /**
-   * Determines if there is an active transaction open.
-   *
-   * @return
-   *   TRUE if we're currently in a transaction, FALSE otherwise.
-   */
-  public function inTransaction() {
-    return ($this->transactionDepth() > 0);
-  }
-
-  /**
-   * Determines current transaction depth.
-   */
-  public function transactionDepth() {
-    return count($this->transactionLayers);
-  }
-
-  /**
-   * Returns a new DatabaseTransaction object on this connection.
-   *
-   * @param $name
-   *   Optional name of the savepoint.
-   *
-   * @see DatabaseTransaction
-   */
-  public function startTransaction($name = '') {
-    $class = $this->getDriverClass('DatabaseTransaction');
-    return new $class($this, $name);
-  }
-
-  /**
-   * Rolls back the transaction entirely or to a named savepoint.
-   *
-   * This method throws an exception if no transaction is active.
-   *
-   * @param $savepoint_name
-   *   The name of the savepoint. The default, 'drupal_transaction', will roll
-   *   the entire transaction back.
-   *
-   * @throws DatabaseTransactionNoActiveException
-   *
-   * @see DatabaseTransaction::rollback()
-   */
-  public function rollback($savepoint_name = 'drupal_transaction') {
-    if (!$this->supportsTransactions()) {
-      return;
-    }
-    if (!$this->inTransaction()) {
-      throw new DatabaseTransactionNoActiveException();
-    }
-    // A previous rollback to an earlier savepoint may mean that the savepoint
-    // in question has already been accidentally committed.
-    if (!isset($this->transactionLayers[$savepoint_name])) {
-      throw new DatabaseTransactionNoActiveException();
-    }
-
-    // We need to find the point we're rolling back to, all other savepoints
-    // before are no longer needed. If we rolled back other active savepoints,
-    // we need to throw an exception.
-    $rolled_back_other_active_savepoints = FALSE;
-    while ($savepoint = array_pop($this->transactionLayers)) {
-      if ($savepoint == $savepoint_name) {
-        // If it is the last the transaction in the stack, then it is not a
-        // savepoint, it is the transaction itself so we will need to roll back
-        // the transaction rather than a savepoint.
-        if (empty($this->transactionLayers)) {
-          break;
-        }
-        $this->query('ROLLBACK TO SAVEPOINT ' . $savepoint);
-        $this->popCommittableTransactions();
-        if ($rolled_back_other_active_savepoints) {
-          throw new DatabaseTransactionOutOfOrderException();
-        }
-        return;
-      }
-      else {
-        $rolled_back_other_active_savepoints = TRUE;
-      }
-    }
-    parent::rollBack();
-    if ($rolled_back_other_active_savepoints) {
-      throw new DatabaseTransactionOutOfOrderException();
-    }
-  }
-
-  /**
-   * Increases the depth of transaction nesting.
-   *
-   * If no transaction is already active, we begin a new transaction.
-   *
-   * @throws DatabaseTransactionNameNonUniqueException
-   *
-   * @see DatabaseTransaction
-   */
-  public function pushTransaction($name) {
-    if (!$this->supportsTransactions()) {
-      return;
-    }
-    if (isset($this->transactionLayers[$name])) {
-      throw new DatabaseTransactionNameNonUniqueException($name . " is already in use.");
-    }
-    // If we're already in a transaction then we want to create a savepoint
-    // rather than try to create another transaction.
-    if ($this->inTransaction()) {
-      $this->query('SAVEPOINT ' . $name);
-    }
-    else {
-      parent::beginTransaction();
-    }
-    $this->transactionLayers[$name] = $name;
-  }
-
-  /**
-   * Decreases the depth of transaction nesting.
-   *
-   * If we pop off the last transaction layer, then we either commit or roll
-   * back the transaction as necessary. If no transaction is active, we return
-   * because the transaction may have manually been rolled back.
-   *
-   * @param $name
-   *   The name of the savepoint
-   *
-   * @throws DatabaseTransactionNoActiveException
-   * @throws DatabaseTransactionCommitFailedException
-   *
-   * @see DatabaseTransaction
-   */
-  public function popTransaction($name) {
-    if (!$this->supportsTransactions()) {
-      return;
-    }
-    // The transaction has already been committed earlier. There is nothing we
-    // need to do. If this transaction was part of an earlier out-of-order
-    // rollback, an exception would already have been thrown by
-    // Database::rollback().
-    if (!isset($this->transactionLayers[$name])) {
-      return;
-    }
-
-    // Mark this layer as committable.
-    $this->transactionLayers[$name] = FALSE;
-    $this->popCommittableTransactions();
-  }
-
-  /**
-   * Internal function: commit all the transaction layers that can commit.
-   */
-  protected function popCommittableTransactions() {
-    // Commit all the committable layers.
-    foreach (array_reverse($this->transactionLayers) as $name => $active) {
-      // Stop once we found an active transaction.
-      if ($active) {
-        break;
-      }
-
-      // If there are no more layers left then we should commit.
-      unset($this->transactionLayers[$name]);
-      if (empty($this->transactionLayers)) {
-        if (!parent::commit()) {
-          throw new DatabaseTransactionCommitFailedException();
-        }
-      }
-      else {
-        $this->query('RELEASE SAVEPOINT ' . $name);
-      }
-    }
-  }
-
-  /**
-   * Runs a limited-range query on this database object.
-   *
-   * Use this as a substitute for ->query() when a subset of the query is to be
-   * returned. User-supplied arguments to the query should be passed in as
-   * separate parameters so that they can be properly escaped to avoid SQL
-   * injection attacks.
-   *
-   * @param $query
-   *   A string containing an SQL query.
-   * @param $args
-   *   An array of values to substitute into the query at placeholder markers.
-   * @param $from
-   *   The first result row to return.
-   * @param $count
-   *   The maximum number of result rows to return.
-   * @param $options
-   *   An array of options on the query.
-   *
-   * @return DatabaseStatementInterface
-   *   A database query result resource, or NULL if the query was not executed
-   *   correctly.
-   */
-  abstract public function queryRange($query, $from, $count, array $args = array(), array $options = array());
-
-  /**
-   * Generates a temporary table name.
-   *
-   * @return
-   *   A table name.
-   */
-  protected function generateTemporaryTableName() {
-    return "db_temporary_" . $this->temporaryNameIndex++;
-  }
-
-  /**
-   * Runs a SELECT query and stores its results in a temporary table.
-   *
-   * Use this as a substitute for ->query() when the results need to stored
-   * in a temporary table. Temporary tables exist for the duration of the page
-   * request. User-supplied arguments to the query should be passed in as
-   * separate parameters so that they can be properly escaped to avoid SQL
-   * injection attacks.
-   *
-   * Note that if you need to know how many results were returned, you should do
-   * a SELECT COUNT(*) on the temporary table afterwards.
-   *
-   * @param $query
-   *   A string containing a normal SELECT SQL query.
-   * @param $args
-   *   An array of values to substitute into the query at placeholder markers.
-   * @param $options
-   *   An associative array of options to control how the query is run. See
-   *   the documentation for DatabaseConnection::defaultOptions() for details.
-   *
-   * @return
-   *   The name of the temporary table.
-   */
-  abstract function queryTemporary($query, array $args = array(), array $options = array());
-
-  /**
-   * Returns the type of database driver.
-   *
-   * This is not necessarily the same as the type of the database itself. For
-   * instance, there could be two MySQL drivers, mysql and mysql_mock. This
-   * function would return different values for each, but both would return
-   * "mysql" for databaseType().
-   */
-  abstract public function driver();
-
-  /**
-   * Returns the version of the database server.
-   */
-  public function version() {
-    return $this->getAttribute(PDO::ATTR_SERVER_VERSION);
-  }
-
-  /**
-   * Determines if this driver supports transactions.
-   *
-   * @return
-   *   TRUE if this connection supports transactions, FALSE otherwise.
-   */
-  public function supportsTransactions() {
-    return $this->transactionSupport;
-  }
-
-  /**
-   * Determines if this driver supports transactional DDL.
-   *
-   * DDL queries are those that change the schema, such as ALTER queries.
-   *
-   * @return
-   *   TRUE if this connection supports transactions for DDL queries, FALSE
-   *   otherwise.
-   */
-  public function supportsTransactionalDDL() {
-    return $this->transactionalDDLSupport;
-  }
-
-  /**
-   * Returns the name of the PDO driver for this connection.
-   */
-  abstract public function databaseType();
-
-
-  /**
-   * Gets any special processing requirements for the condition operator.
-   *
-   * Some condition types require special processing, such as IN, because
-   * the value data they pass in is not a simple value. This is a simple
-   * overridable lookup function. Database connections should define only
-   * those operators they wish to be handled differently than the default.
-   *
-   * @param $operator
-   *   The condition operator, such as "IN", "BETWEEN", etc. Case-sensitive.
-   *
-   * @return
-   *   The extra handling directives for the specified operator, or NULL.
-   *
-   * @see DatabaseCondition::compile()
-   */
-  abstract public function mapConditionOperator($operator);
-
-  /**
-   * Throws an exception to deny direct access to transaction commits.
-   *
-   * We do not want to allow users to commit transactions at any time, only
-   * by destroying the transaction object or allowing it to go out of scope.
-   * A direct commit bypasses all of the safety checks we've built on top of
-   * PDO's transaction routines.
-   *
-   * @throws DatabaseTransactionExplicitCommitNotAllowedException
-   *
-   * @see DatabaseTransaction
-   */
-  public function commit() {
-    throw new DatabaseTransactionExplicitCommitNotAllowedException();
-  }
-
-  /**
-   * Retrieves an unique id from a given sequence.
-   *
-   * Use this function if for some reason you can't use a serial field. For
-   * example, MySQL has no ways of reading of the current value of a sequence
-   * and PostgreSQL can not advance the sequence to be larger than a given
-   * value. Or sometimes you just need a unique integer.
-   *
-   * @param $existing_id
-   *   After a database import, it might be that the sequences table is behind,
-   *   so by passing in the maximum existing id, it can be assured that we
-   *   never issue the same id.
-   *
-   * @return
-   *   An integer number larger than any number returned by earlier calls and
-   *   also larger than the $existing_id if one was passed in.
-   */
-  abstract public function nextId($existing_id = 0);
-}
-
-/**
- * Primary front-controller for the database system.
- *
- * This class is uninstantiatable and un-extendable. It acts to encapsulate
- * all control and shepherding of database connections into a single location
- * without the use of globals.
- */
-abstract class Database {
-
-  /**
-   * Flag to indicate a query call should simply return NULL.
-   *
-   * This is used for queries that have no reasonable return value anyway, such
-   * as INSERT statements to a table without a serial primary key.
-   */
-  const RETURN_NULL = 0;
-
-  /**
-   * Flag to indicate a query call should return the prepared statement.
-   */
-  const RETURN_STATEMENT = 1;
-
-  /**
-   * Flag to indicate a query call should return the number of affected rows.
-   */
-  const RETURN_AFFECTED = 2;
-
-  /**
-   * Flag to indicate a query call should return the "last insert id".
-   */
-  const RETURN_INSERT_ID = 3;
-
-  /**
-   * An nested array of all active connections. It is keyed by database name
-   * and target.
-   *
-   * @var array
-   */
-  static protected $connections = array();
-
-  /**
-   * A processed copy of the database connection information from settings.php.
-   *
-   * @var array
-   */
-  static protected $databaseInfo = NULL;
-
-  /**
-   * A list of key/target credentials to simply ignore.
-   *
-   * @var array
-   */
-  static protected $ignoreTargets = array();
-
-  /**
-   * The key of the currently active database connection.
-   *
-   * @var string
-   */
-  static protected $activeKey = 'default';
-
-  /**
-   * An array of active query log objects.
-   *
-   * Every connection has one and only one logger object for all targets and
-   * logging keys.
-   *
-   * array(
-   *   '$db_key' => DatabaseLog object.
-   * );
-   *
-   * @var array
-   */
-  static protected $logs = array();
-
-  /**
-   * Starts logging a given logging key on the specified connection.
-   *
-   * @param $logging_key
-   *   The logging key to log.
-   * @param $key
-   *   The database connection key for which we want to log.
-   *
-   * @return DatabaseLog
-   *   The query log object. Note that the log object does support richer
-   *   methods than the few exposed through the Database class, so in some
-   *   cases it may be desirable to access it directly.
-   *
-   * @see DatabaseLog
-   */
-  final public static function startLog($logging_key, $key = 'default') {
-    if (empty(self::$logs[$key])) {
-      self::$logs[$key] = new DatabaseLog($key);
-
-      // Every target already active for this connection key needs to have the
-      // logging object associated with it.
-      if (!empty(self::$connections[$key])) {
-        foreach (self::$connections[$key] as $connection) {
-          $connection->setLogger(self::$logs[$key]);
-        }
-      }
-    }
-
-    self::$logs[$key]->start($logging_key);
-    return self::$logs[$key];
-  }
-
-  /**
-   * Retrieves the queries logged on for given logging key.
-   *
-   * This method also ends logging for the specified key. To get the query log
-   * to date without ending the logger request the logging object by starting
-   * it again (which does nothing to an open log key) and call methods on it as
-   * desired.
-   *
-   * @param $logging_key
-   *   The logging key to log.
-   * @param $key
-   *   The database connection key for which we want to log.
-   *
-   * @return array
-   *   The query log for the specified logging key and connection.
-   *
-   * @see DatabaseLog
-   */
-  final public static function getLog($logging_key, $key = 'default') {
-    if (empty(self::$logs[$key])) {
-      return NULL;
-    }
-    $queries = self::$logs[$key]->get($logging_key);
-    self::$logs[$key]->end($logging_key);
-    return $queries;
-  }
-
-  /**
-   * Gets the connection object for the specified database key and target.
-   *
-   * @param $target
-   *   The database target name.
-   * @param $key
-   *   The database connection key. Defaults to NULL which means the active key.
-   *
-   * @return DatabaseConnection
-   *   The corresponding connection object.
-   */
-  final public static function getConnection($target = 'default', $key = NULL) {
-    if (!isset($key)) {
-      // By default, we want the active connection, set in setActiveConnection.
-      $key = self::$activeKey;
-    }
-    // If the requested target does not exist, or if it is ignored, we fall back
-    // to the default target. The target is typically either "default" or
-    // "slave", indicating to use a slave SQL server if one is available. If
-    // it's not available, then the default/master server is the correct server
-    // to use.
-    if (!empty(self::$ignoreTargets[$key][$target]) || !isset(self::$databaseInfo[$key][$target])) {
-      $target = 'default';
-    }
-
-    if (!isset(self::$connections[$key][$target])) {
-      // If necessary, a new connection is opened.
-      self::$connections[$key][$target] = self::openConnection($key, $target);
-    }
-    return self::$connections[$key][$target];
-  }
-
-  /**
-   * Determines if there is an active connection.
-   *
-   * Note that this method will return FALSE if no connection has been
-   * established yet, even if one could be.
-   *
-   * @return
-   *   TRUE if there is at least one database connection established, FALSE
-   *   otherwise.
-   */
-  final public static function isActiveConnection() {
-    return !empty(self::$activeKey) && !empty(self::$connections) && !empty(self::$connections[self::$activeKey]);
-  }
-
-  /**
-   * Sets the active connection to the specified key.
-   *
-   * @return
-   *   The previous database connection key.
-   */
-  final public static function setActiveConnection($key = 'default') {
-    if (empty(self::$databaseInfo)) {
-      self::parseConnectionInfo();
-    }
-
-    if (!empty(self::$databaseInfo[$key])) {
-      $old_key = self::$activeKey;
-      self::$activeKey = $key;
-      return $old_key;
-    }
-  }
-
-  /**
-   * Process the configuration file for database information.
-   */
-  final public static function parseConnectionInfo() {
-    global $databases;
-
-    $database_info = is_array($databases) ? $databases : array();
-    foreach ($database_info as $index => $info) {
-      foreach ($database_info[$index] as $target => $value) {
-        // If there is no "driver" property, then we assume it's an array of
-        // possible connections for this target. Pick one at random. That allows
-        //  us to have, for example, multiple slave servers.
-        if (empty($value['driver'])) {
-          $database_info[$index][$target] = $database_info[$index][$target][mt_rand(0, count($database_info[$index][$target]) - 1)];
-        }
-
-        // Parse the prefix information.
-        if (!isset($database_info[$index][$target]['prefix'])) {
-          // Default to an empty prefix.
-          $database_info[$index][$target]['prefix'] = array(
-            'default' => '',
-          );
-        }
-        elseif (!is_array($database_info[$index][$target]['prefix'])) {
-          // Transform the flat form into an array form.
-          $database_info[$index][$target]['prefix'] = array(
-            'default' => $database_info[$index][$target]['prefix'],
-          );
-        }
-      }
-    }
-
-    if (!is_array(self::$databaseInfo)) {
-      self::$databaseInfo = $database_info;
-    }
-
-    // Merge the new $database_info into the existing.
-    // array_merge_recursive() cannot be used, as it would make multiple
-    // database, user, and password keys in the same database array.
-    else {
-      foreach ($database_info as $database_key => $database_values) {
-        foreach ($database_values as $target => $target_values) {
-          self::$databaseInfo[$database_key][$target] = $target_values;
-        }
-      }
-    }
-  }
-
-  /**
-   * Adds database connection information for a given key/target.
-   *
-   * This method allows the addition of new connection credentials at runtime.
-   * Under normal circumstances the preferred way to specify database
-   * credentials is via settings.php. However, this method allows them to be
-   * added at arbitrary times, such as during unit tests, when connecting to
-   * admin-defined third party databases, etc.
-   *
-   * If the given key/target pair already exists, this method will be ignored.
-   *
-   * @param $key
-   *   The database key.
-   * @param $target
-   *   The database target name.
-   * @param $info
-   *   The database connection information, as it would be defined in
-   *   settings.php. Note that the structure of this array will depend on the
-   *   database driver it is connecting to.
-   */
-  public static function addConnectionInfo($key, $target, $info) {
-    if (empty(self::$databaseInfo[$key][$target])) {
-      self::$databaseInfo[$key][$target] = $info;
-    }
-  }
-
-  /**
-   * Gets information on the specified database connection.
-   *
-   * @param $connection
-   *   The connection key for which we want information.
-   */
-  final public static function getConnectionInfo($key = 'default') {
-    if (empty(self::$databaseInfo)) {
-      self::parseConnectionInfo();
-    }
-
-    if (!empty(self::$databaseInfo[$key])) {
-      return self::$databaseInfo[$key];
-    }
-  }
-
-  /**
-   * Rename a connection and its corresponding connection information.
-   *
-   * @param $old_key
-   *   The old connection key.
-   * @param $new_key
-   *   The new connection key.
-   * @return
-   *   TRUE in case of success, FALSE otherwise.
-   */
-  final public static function renameConnection($old_key, $new_key) {
-    if (empty(self::$databaseInfo)) {
-      self::parseConnectionInfo();
-    }
-
-    if (!empty(self::$databaseInfo[$old_key]) && empty(self::$databaseInfo[$new_key])) {
-      // Migrate the database connection information.
-      self::$databaseInfo[$new_key] = self::$databaseInfo[$old_key];
-      unset(self::$databaseInfo[$old_key]);
-
-      // Migrate over the DatabaseConnection object if it exists.
-      if (isset(self::$connections[$old_key])) {
-        self::$connections[$new_key] = self::$connections[$old_key];
-        unset(self::$connections[$old_key]);
-      }
-
-      return TRUE;
-    }
-    else {
-      return FALSE;
-    }
-  }
-
-  /**
-   * Remove a connection and its corresponding connection information.
-   *
-   * @param $key
-   *   The connection key.
-   * @return
-   *   TRUE in case of success, FALSE otherwise.
-   */
-  final public static function removeConnection($key) {
-    if (isset(self::$databaseInfo[$key])) {
-      unset(self::$databaseInfo[$key]);
-      unset(self::$connections[$key]);
-      return TRUE;
-    }
-    else {
-      return FALSE;
-    }
-  }
-
-  /**
-   * Opens a connection to the server specified by the given key and target.
-   *
-   * @param $key
-   *   The database connection key, as specified in settings.php. The default is
-   *   "default".
-   * @param $target
-   *   The database target to open.
-   *
-   * @throws DatabaseConnectionNotDefinedException
-   * @throws DatabaseDriverNotSpecifiedException
-   */
-  final protected static function openConnection($key, $target) {
-    if (empty(self::$databaseInfo)) {
-      self::parseConnectionInfo();
-    }
-
-    // If the requested database does not exist then it is an unrecoverable
-    // error.
-    if (!isset(self::$databaseInfo[$key])) {
-      throw new DatabaseConnectionNotDefinedException('The specified database connection is not defined: ' . $key);
-    }
-
-    if (!$driver = self::$databaseInfo[$key][$target]['driver']) {
-      throw new DatabaseDriverNotSpecifiedException('Driver not specified for this database connection: ' . $key);
-    }
-
-    // We cannot rely on the registry yet, because the registry requires an
-    // open database connection.
-    $driver_class = 'DatabaseConnection_' . $driver;
-    require_once DRUPAL_ROOT . '/core/includes/database/' . $driver . '/database.inc';
-    $new_connection = new $driver_class(self::$databaseInfo[$key][$target]);
-    $new_connection->setTarget($target);
-    $new_connection->setKey($key);
-
-    // If we have any active logging objects for this connection key, we need
-    // to associate them with the connection we just opened.
-    if (!empty(self::$logs[$key])) {
-      $new_connection->setLogger(self::$logs[$key]);
-    }
-
-    return $new_connection;
-  }
-
-  /**
-   * Closes a connection to the server specified by the given key and target.
-   *
-   * @param $target
-   *   The database target name.  Defaults to NULL meaning that all target
-   *   connections will be closed.
-   * @param $key
-   *   The database connection key. Defaults to NULL which means the active key.
-   */
-  public static function closeConnection($target = NULL, $key = NULL) {
-    // Gets the active connection by default.
-    if (!isset($key)) {
-      $key = self::$activeKey;
-    }
-    // To close the connection, we need to unset the static variable.
-    if (isset($target)) {
-      unset(self::$connections[$key][$target]);
-    }
-    else {
-      unset(self::$connections[$key]);
-    }
-  }
-
-  /**
-   * Instructs the system to temporarily ignore a given key/target.
-   *
-   * At times we need to temporarily disable slave queries. To do so, call this
-   * method with the database key and the target to disable. That database key
-   * will then always fall back to 'default' for that key, even if it's defined.
-   *
-   * @param $key
-   *   The database connection key.
-   * @param $target
-   *   The target of the specified key to ignore.
-   */
-  public static function ignoreTarget($key, $target) {
-    self::$ignoreTargets[$key][$target] = TRUE;
-  }
-
-  /**
-   * Load a file for the database that might hold a class.
-   *
-   * @param $driver
-   *   The name of the driver.
-   * @param array $files
-   *   The name of the files the driver specific class can be.
-   */
-  public static function loadDriverFile($driver, array $files = array()) {
-    static $base_path;
-
-    if (empty($base_path)) {
-      $base_path = dirname(realpath(__FILE__));
-    }
-
-    $driver_base_path = "$base_path/$driver";
-    foreach ($files as $file) {
-      // Load the base file first so that classes extending base classes will
-      // have the base class loaded.
-      foreach (array("$base_path/$file", "$driver_base_path/$file") as $filename) {
-        // The OS caches file_exists() and PHP caches require_once(), so
-        // we'll let both of those take care of performance here.
-        if (file_exists($filename)) {
-          require_once $filename;
-        }
-      }
-    }
-  }
-}
-
-/**
- * Exception for when popTransaction() is called with no active transaction.
- */
-class DatabaseTransactionNoActiveException extends Exception { }
-
-/**
- * Exception thrown when a savepoint or transaction name occurs twice.
- */
-class DatabaseTransactionNameNonUniqueException extends Exception { }
-
-/**
- * Exception thrown when a commit() function fails.
- */
-class DatabaseTransactionCommitFailedException extends Exception { }
-
-/**
- * Exception to deny attempts to explicitly manage transactions.
- *
- * This exception will be thrown when the PDO connection commit() is called.
- * Code should never call this method directly.
- */
-class DatabaseTransactionExplicitCommitNotAllowedException extends Exception { }
-
-/**
- * Exception thrown when a rollback() resulted in other active transactions being rolled-back.
- */
-class DatabaseTransactionOutOfOrderException extends Exception { }
-
-/**
- * Exception thrown for merge queries that do not make semantic sense.
- *
- * There are many ways that a merge query could be malformed.  They should all
- * throw this exception and set an appropriately descriptive message.
- */
-class InvalidMergeQueryException extends Exception {}
-
-/**
- * Exception thrown if an insert query specifies a field twice.
- *
- * It is not allowed to specify a field as default and insert field, this
- * exception is thrown if that is the case.
- */
-class FieldsOverlapException extends Exception {}
-
-/**
- * Exception thrown if an insert query doesn't specify insert or default fields.
- */
-class NoFieldsException extends Exception {}
-
-/**
- * Exception thrown if an undefined database connection is requested.
- */
-class DatabaseConnectionNotDefinedException extends Exception {}
-
-/**
- * Exception thrown if no driver is specified for a database connection.
- */
-class DatabaseDriverNotSpecifiedException extends Exception {}
-
-
-/**
- * A wrapper class for creating and managing database transactions.
- *
- * Not all databases or database configurations support transactions. For
- * example, MySQL MyISAM tables do not. It is also easy to begin a transaction
- * and then forget to commit it, which can lead to connection errors when
- * another transaction is started.
- *
- * This class acts as a wrapper for transactions. To begin a transaction,
- * simply instantiate it. When the object goes out of scope and is destroyed
- * it will automatically commit. It also will check to see if the specified
- * connection supports transactions. If not, it will simply skip any transaction
- * commands, allowing user-space code to proceed normally. The only difference
- * is that rollbacks won't actually do anything.
- *
- * In the vast majority of cases, you should not instantiate this class
- * directly. Instead, call ->startTransaction(), from the appropriate connection
- * object.
- */
-class DatabaseTransaction {
-
-  /**
-   * The connection object for this transaction.
-   *
-   * @var DatabaseConnection
-   */
-  protected $connection;
-
-  /**
-   * A boolean value to indicate whether this transaction has been rolled back.
-   *
-   * @var Boolean
-   */
-  protected $rolledBack = FALSE;
-
-  /**
-   * The name of the transaction.
-   *
-   * This is used to label the transaction savepoint. It will be overridden to
-   * 'drupal_transaction' if there is no transaction depth.
-   */
-  protected $name;
-
-  public function __construct(DatabaseConnection &$connection, $name = NULL) {
-    $this->connection = &$connection;
-    // If there is no transaction depth, then no transaction has started. Name
-    // the transaction 'drupal_transaction'.
-    if (!$depth = $connection->transactionDepth()) {
-      $this->name = 'drupal_transaction';
-    }
-    // Within transactions, savepoints are used. Each savepoint requires a
-    // name. So if no name is present we need to create one.
-    elseif (!$name) {
-      $this->name = 'savepoint_' . $depth;
-    }
-    else {
-      $this->name = $name;
-    }
-    $this->connection->pushTransaction($this->name);
-  }
-
-  public function __destruct() {
-    // If we rolled back then the transaction would have already been popped.
-    if (!$this->rolledBack) {
-      $this->connection->popTransaction($this->name);
-    }
-  }
-
-  /**
-   * Retrieves the name of the transaction or savepoint.
-   */
-  public function name() {
-    return $this->name;
-  }
-
-  /**
-   * Rolls back the current transaction.
-   *
-   * This is just a wrapper method to rollback whatever transaction stack we are
-   * currently in, which is managed by the connection object itself. Note that
-   * logging (preferable with watchdog_exception()) needs to happen after a
-   * transaction has been rolled back or the log messages will be rolled back
-   * too.
-   *
-   * @see DatabaseConnection::rollback()
-   * @see watchdog_exception()
-   */
-  public function rollback() {
-    $this->rolledBack = TRUE;
-    $this->connection->rollback($this->name);
-  }
-}
-
-/**
- * Represents a prepared statement.
- *
- * Some methods in that class are purposefully commented out. Due to a change in
- * how PHP defines PDOStatement, we can't define a signature for those methods
- * that will work the same way between versions older than 5.2.6 and later
- * versions.  See http://bugs.php.net/bug.php?id=42452 for more details.
- *
- * Child implementations should either extend PDOStatement:
- * @code
- * class DatabaseStatement_oracle extends PDOStatement implements DatabaseStatementInterface {}
- * @endcode
- * or define their own class. If defining their own class, they will also have
- * to implement either the Iterator or IteratorAggregate interface before
- * DatabaseStatementInterface:
- * @code
- * class DatabaseStatement_oracle implements Iterator, DatabaseStatementInterface {}
- * @endcode
- */
-interface DatabaseStatementInterface extends Traversable {
-
-  /**
-   * Executes a prepared statement
-   *
-   * @param $args
-   *   An array of values with as many elements as there are bound parameters in
-   *   the SQL statement being executed.
-   * @param $options
-   *   An array of options for this query.
-   *
-   * @return
-   *   TRUE on success, or FALSE on failure.
-   */
-  public function execute($args = array(), $options = array());
-
-  /**
-   * Gets the query string of this statement.
-   *
-   * @return
-   *   The query string, in its form with placeholders.
-   */
-  public function getQueryString();
-
-  /**
-   * Returns the number of rows affected by the last SQL statement.
-   *
-   * @return
-   *   The number of rows affected by the last DELETE, INSERT, or UPDATE
-   *   statement executed.
-   */
-  public function rowCount();
-
-  /**
-   * Sets the default fetch mode for this statement.
-   *
-   * See http://php.net/manual/en/pdo.constants.php for the definition of the
-   * constants used.
-   *
-   * @param $mode
-   *   One of the PDO::FETCH_* constants.
-   * @param $a1
-   *   An option depending of the fetch mode specified by $mode:
-   *   - for PDO::FETCH_COLUMN, the index of the column to fetch
-   *   - for PDO::FETCH_CLASS, the name of the class to create
-   *   - for PDO::FETCH_INTO, the object to add the data to
-   * @param $a2
-   *   If $mode is PDO::FETCH_CLASS, the optional arguments to pass to the
-   *   constructor.
-   */
-  // public function setFetchMode($mode, $a1 = NULL, $a2 = array());
-
-  /**
-   * Fetches the next row from a result set.
-   *
-   * See http://php.net/manual/en/pdo.constants.php for the definition of the
-   * constants used.
-   *
-   * @param $mode
-   *   One of the PDO::FETCH_* constants.
-   *   Default to what was specified by setFetchMode().
-   * @param $cursor_orientation
-   *   Not implemented in all database drivers, don't use.
-   * @param $cursor_offset
-   *   Not implemented in all database drivers, don't use.
-   *
-   * @return
-   *   A result, formatted according to $mode.
-   */
-  // public function fetch($mode = NULL, $cursor_orientation = NULL, $cursor_offset = NULL);
-
-  /**
-   * Returns a single field from the next record of a result set.
-   *
-   * @param $index
-   *   The numeric index of the field to return. Defaults to the first field.
-   *
-   * @return
-   *   A single field from the next record, or FALSE if there is no next record.
-   */
-  public function fetchField($index = 0);
-
-  /**
-   * Fetches the next row and returns it as an object.
-   *
-   * The object will be of the class specified by DatabaseStatementInterface::setFetchMode()
-   * or stdClass if not specified.
-   */
-  // public function fetchObject();
-
-  /**
-   * Fetches the next row and returns it as an associative array.
-   *
-   * This method corresponds to PDOStatement::fetchObject(), but for associative
-   * arrays. For some reason PDOStatement does not have a corresponding array
-   * helper method, so one is added.
-   *
-   * @return
-   *   An associative array, or FALSE if there is no next row.
-   */
-  public function fetchAssoc();
-
-  /**
-   * Returns an array containing all of the result set rows.
-   *
-   * @param $mode
-   *   One of the PDO::FETCH_* constants.
-   * @param $column_index
-   *   If $mode is PDO::FETCH_COLUMN, the index of the column to fetch.
-   * @param $constructor_arguments
-   *   If $mode is PDO::FETCH_CLASS, the arguments to pass to the constructor.
-   *
-   * @return
-   *   An array of results.
-   */
-  // function fetchAll($mode = NULL, $column_index = NULL, array $constructor_arguments);
-
-  /**
-   * Returns an entire single column of a result set as an indexed array.
-   *
-   * Note that this method will run the result set to the end.
-   *
-   * @param $index
-   *   The index of the column number to fetch.
-   *
-   * @return
-   *   An indexed array, or an empty array if there is no result set.
-   */
-  public function fetchCol($index = 0);
-
-  /**
-   * Returns the entire result set as a single associative array.
-   *
-   * This method is only useful for two-column result sets. It will return an
-   * associative array where the key is one column from the result set and the
-   * value is another field. In most cases, the default of the first two columns
-   * is appropriate.
-   *
-   * Note that this method will run the result set to the end.
-   *
-   * @param $key_index
-   *   The numeric index of the field to use as the array key.
-   * @param $value_index
-   *   The numeric index of the field to use as the array value.
-   *
-   * @return
-   *   An associative array, or an empty array if there is no result set.
-   */
-  public function fetchAllKeyed($key_index = 0, $value_index = 1);
-
-  /**
-   * Returns the result set as an associative array keyed by the given field.
-   *
-   * If the given key appears multiple times, later records will overwrite
-   * earlier ones.
-   *
-   * @param $key
-   *   The name of the field on which to index the array.
-   * @param $fetch
-   *   The fetchmode to use. If set to PDO::FETCH_ASSOC, PDO::FETCH_NUM, or
-   *   PDO::FETCH_BOTH the returned value with be an array of arrays. For any
-   *   other value it will be an array of objects. By default, the fetch mode
-   *   set for the query will be used.
-   *
-   * @return
-   *   An associative array, or an empty array if there is no result set.
-   */
-  public function fetchAllAssoc($key, $fetch = NULL);
-}
-
-/**
- * Default implementation of DatabaseStatementInterface.
- *
- * PDO allows us to extend the PDOStatement class to provide additional
- * functionality beyond that offered by default. We do need extra
- * functionality. By default, this class is not driver-specific. If a given
- * driver needs to set a custom statement class, it may do so in its
- * constructor.
- *
- * @see http://us.php.net/pdostatement
- */
-class DatabaseStatementBase extends PDOStatement implements DatabaseStatementInterface {
-
-  /**
-   * Reference to the database connection object for this statement.
-   *
-   * The name $dbh is inherited from PDOStatement.
-   *
-   * @var DatabaseConnection
-   */
-  public $dbh;
-
-  protected function __construct($dbh) {
-    $this->dbh = $dbh;
-    $this->setFetchMode(PDO::FETCH_OBJ);
-  }
-
-  public function execute($args = array(), $options = array()) {
-    if (isset($options['fetch'])) {
-      if (is_string($options['fetch'])) {
-        // Default to an object. Note: db fields will be added to the object
-        // before the constructor is run. If you need to assign fields after
-        // the constructor is run, see http://drupal.org/node/315092.
-        $this->setFetchMode(PDO::FETCH_CLASS, $options['fetch']);
-      }
-      else {
-        $this->setFetchMode($options['fetch']);
-      }
-    }
-
-    $logger = $this->dbh->getLogger();
-    if (!empty($logger)) {
-      $query_start = microtime(TRUE);
-    }
-
-    $return = parent::execute($args);
-
-    if (!empty($logger)) {
-      $query_end = microtime(TRUE);
-      $logger->log($this, $args, $query_end - $query_start);
-    }
-
-    return $return;
-  }
-
-  public function getQueryString() {
-    return $this->queryString;
-  }
-
-  public function fetchCol($index = 0) {
-    return $this->fetchAll(PDO::FETCH_COLUMN, $index);
-  }
-
-  public function fetchAllAssoc($key, $fetch = NULL) {
-    $return = array();
-    if (isset($fetch)) {
-      if (is_string($fetch)) {
-        $this->setFetchMode(PDO::FETCH_CLASS, $fetch);
-      }
-      else {
-        $this->setFetchMode($fetch);
-      }
-    }
-
-    foreach ($this as $record) {
-      $record_key = is_object($record) ? $record->$key : $record[$key];
-      $return[$record_key] = $record;
-    }
-
-    return $return;
-  }
-
-  public function fetchAllKeyed($key_index = 0, $value_index = 1) {
-    $return = array();
-    $this->setFetchMode(PDO::FETCH_NUM);
-    foreach ($this as $record) {
-      $return[$record[$key_index]] = $record[$value_index];
-    }
-    return $return;
-  }
-
-  public function fetchField($index = 0) {
-    // Call PDOStatement::fetchColumn to fetch the field.
-    return $this->fetchColumn($index);
-  }
-
-  public function fetchAssoc() {
-    // Call PDOStatement::fetch to fetch the row.
-    return $this->fetch(PDO::FETCH_ASSOC);
-  }
-}
-
-/**
- * Empty implementation of a database statement.
- *
- * This class satisfies the requirements of being a database statement/result
- * object, but does not actually contain data.  It is useful when developers
- * need to safely return an "empty" result set without connecting to an actual
- * database.  Calling code can then treat it the same as if it were an actual
- * result set that happens to contain no records.
- *
- * @see SearchQuery
- */
-class DatabaseStatementEmpty implements Iterator, DatabaseStatementInterface {
-
-  public function execute($args = array(), $options = array()) {
-    return FALSE;
-  }
-
-  public function getQueryString() {
-    return '';
-  }
-
-  public function rowCount() {
-    return 0;
-  }
-
-  public function setFetchMode($mode, $a1 = NULL, $a2 = array()) {
-    return;
-  }
-
-  public function fetch($mode = NULL, $cursor_orientation = NULL, $cursor_offset = NULL) {
-    return NULL;
-  }
-
-  public function fetchField($index = 0) {
-    return NULL;
-  }
-
-  public function fetchObject() {
-    return NULL;
-  }
-
-  public function fetchAssoc() {
-    return NULL;
-  }
-
-  function fetchAll($mode = NULL, $column_index = NULL, array $constructor_arguments = array()) {
-    return array();
-  }
-
-  public function fetchCol($index = 0) {
-    return array();
-  }
-
-  public function fetchAllKeyed($key_index = 0, $value_index = 1) {
-    return array();
-  }
-
-  public function fetchAllAssoc($key, $fetch = NULL) {
-    return array();
-  }
-
-  /* Implementations of Iterator. */
-
-  public function current() {
-    return NULL;
-  }
-
-  public function key() {
-    return NULL;
-  }
-
-  public function rewind() {
-    // Nothing to do: our DatabaseStatement can't be rewound.
-  }
-
-  public function next() {
-    // Do nothing, since this is an always-empty implementation.
-  }
-
-  public function valid() {
-    return FALSE;
-  }
-}
-
 /**
  * The following utility functions are simply convenience wrappers.
  *
@@ -2630,28 +530,28 @@ function db_next_id($existing_id = 0) {
 /**
  * Returns a new DatabaseCondition, set to "OR" all conditions together.
  *
- * @return DatabaseCondition
+ * @return Condition
  */
 function db_or() {
-  return new DatabaseCondition('OR');
+  return new Condition('OR');
 }
 
 /**
  * Returns a new DatabaseCondition, set to "AND" all conditions together.
  *
- * @return DatabaseCondition
+ * @return Condition
  */
 function db_and() {
-  return new DatabaseCondition('AND');
+  return new Condition('AND');
 }
 
 /**
  * Returns a new DatabaseCondition, set to "XOR" all conditions together.
  *
- * @return DatabaseCondition
+ * @return Condition
  */
 function db_xor() {
-  return new DatabaseCondition('XOR');
+  return new Condition('XOR');
 }
 
 /**
@@ -2662,10 +562,10 @@ function db_xor() {
  *
  * @param $conjunction
  *   The conjunction to use for query conditions (AND, OR or XOR).
- * @return DatabaseCondition
+ * @return Condition
  */
 function db_condition($conjunction) {
-  return new DatabaseCondition($conjunction);
+  return new Condition($conjunction);
 }
 
 /**
diff --git a/core/includes/database/query.inc b/core/includes/database/query.inc
deleted file mode 100644
index 0effedae19cd82f367a8d61c28fc45a8734904e3..0000000000000000000000000000000000000000
--- a/core/includes/database/query.inc
+++ /dev/null
@@ -1,1956 +0,0 @@
-<?php
-
-/**
- * @ingroup database
- * @{
- */
-
-/**
- * @file
- * Non-specific Database query code. Used by all engines.
- */
-
-/**
- * Interface for a conditional clause in a query.
- */
-interface QueryConditionInterface {
-
-  /**
-   * Helper function: builds the most common conditional clauses.
-   *
-   * This method can take a variable number of parameters. If called with two
-   * parameters, they are taken as $field and $value with $operator having a
-   * value of IN if $value is an array and = otherwise.
-   *
-   * Do not use this method to test for NULL values. Instead, use
-   * QueryConditionInterface::isNull() or QueryConditionInterface::isNotNull().
-   *
-   * @param $field
-   *   The name of the field to check. If you would like to add a more complex
-   *   condition involving operators or functions, use where().
-   * @param $value
-   *   The value to test the field against. In most cases, this is a scalar.
-   *   For more complex options, it is an array. The meaning of each element in
-   *   the array is dependent on the $operator.
-   * @param $operator
-   *   The comparison operator, such as =, <, or >=. It also accepts more
-   *   complex options such as IN, LIKE, or BETWEEN. Defaults to IN if $value is
-   *   an array, and = otherwise.
-   *
-   * @return QueryConditionInterface
-   *   The called object.
-   *
-   * @see QueryConditionInterface::isNull()
-   * @see QueryConditionInterface::isNotNull()
-   */
-  public function condition($field, $value = NULL, $operator = NULL);
-
-  /**
-   * Adds an arbitrary WHERE clause to the query.
-   *
-   * @param $snippet
-   *   A portion of a WHERE clause as a prepared statement. It must use named
-   *   placeholders, not ? placeholders.
-   * @param $args
-   *   An associative array of arguments.
-   *
-   * @return QueryConditionInterface
-   *   The called object.
-   */
-  public function where($snippet, $args = array());
-
-  /**
-   * Sets a condition that the specified field be NULL.
-   *
-   * @param $field
-   *   The name of the field to check.
-   *
-   * @return QueryConditionInterface
-   *   The called object.
-   */
-  public function isNull($field);
-
-  /**
-   * Sets a condition that the specified field be NOT NULL.
-   *
-   * @param $field
-   *   The name of the field to check.
-   *
-   * @return QueryConditionInterface
-   *   The called object.
-   */
-  public function isNotNull($field);
-
-  /**
-   * Sets a condition that the specified subquery returns values.
-   * 
-   * @param SelectQueryInterface $select
-   *   The subquery that must contain results.
-   *
-   * @return QueryConditionInterface
-   *   The called object.
-   */
-  public function exists(SelectQueryInterface $select);
-  
-  /**
-   * Sets a condition that the specified subquery returns no values.
-   * 
-   * @param SelectQueryInterface $select
-   *   The subquery that must not contain results.
-   *
-   * @return QueryConditionInterface
-   *   The called object.
-   */
-  public function notExists(SelectQueryInterface $select);
-  
-  /**
-   * Gets a complete list of all conditions in this conditional clause.
-   *
-   * This method returns by reference. That allows alter hooks to access the
-   * data structure directly and manipulate it before it gets compiled.
-   *
-   * The data structure that is returned is an indexed array of entries, where
-   * each entry looks like the following:
-   * @code
-   * array(
-   *   'field' => $field,
-   *   'value' => $value,
-   *   'operator' => $operator,
-   * );
-   * @endcode
-   *
-   * In the special case that $operator is NULL, the $field is taken as a raw
-   * SQL snippet (possibly containing a function) and $value is an associative
-   * array of placeholders for the snippet.
-   *
-   * There will also be a single array entry of #conjunction, which is the
-   * conjunction that will be applied to the array, such as AND.
-   */
-  public function &conditions();
-
-  /**
-   * Gets a complete list of all values to insert into the prepared statement.
-   *
-   * @return
-   *   An associative array of placeholders and values.
-   */
-  public function arguments();
-
-  /**
-   * Compiles the saved conditions for later retrieval.
-   *
-   * This method does not return anything, but simply prepares data to be
-   * retrieved via __toString() and arguments().
-   *
-   * @param $connection
-   *   The database connection for which to compile the conditionals.
-   * @param $queryPlaceholder
-   *   The query this condition belongs to. If not given, the current query is
-   *   used.
-   */
-  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder);
-
-  /**
-   * Check whether a condition has been previously compiled.
-   *
-   * @return
-   *   TRUE if the condition has been previously compiled.
-   */
-  public function compiled();
-}
-
-
-/**
- * Interface for a query that can be manipulated via an alter hook.
- */
-interface QueryAlterableInterface {
-
-  /**
-   * Adds a tag to a query.
-   *
-   * Tags are strings that identify a query. A query may have any number of
-   * tags. Tags are used to mark a query so that alter hooks may decide if they
-   * wish to take action. Tags should be all lower-case and contain only
-   * letters, numbers, and underscore, and start with a letter. That is, they
-   * should follow the same rules as PHP identifiers in general.
-   *
-   * @param $tag
-   *   The tag to add.
-   *
-   * @return QueryAlterableInterface
-   *   The called object.
-   */
-  public function addTag($tag);
-
-  /**
-   * Determines if a given query has a given tag.
-   *
-   * @param $tag
-   *   The tag to check.
-   *
-   * @return
-   *   TRUE if this query has been marked with this tag, FALSE otherwise.
-   */
-  public function hasTag($tag);
-
-  /**
-   * Determines if a given query has all specified tags.
-   *
-   * @param $tags
-   *   A variable number of arguments, one for each tag to check.
-   *
-   * @return
-   *   TRUE if this query has been marked with all specified tags, FALSE
-   *   otherwise.
-   */
-  public function hasAllTags();
-
-  /**
-   * Determines if a given query has any specified tag.
-   *
-   * @param $tags
-   *   A variable number of arguments, one for each tag to check.
-   *
-   * @return
-   *   TRUE if this query has been marked with at least one of the specified
-   *   tags, FALSE otherwise.
-   */
-  public function hasAnyTag();
-
-  /**
-   * Adds additional metadata to the query.
-   *
-   * Often, a query may need to provide additional contextual data to alter
-   * hooks. Alter hooks may then use that information to decide if and how
-   * to take action.
-   *
-   * @param $key
-   *   The unique identifier for this piece of metadata. Must be a string that
-   *   follows the same rules as any other PHP identifier.
-   * @param $object
-   *   The additional data to add to the query. May be any valid PHP variable.
-   *
-   * @return QueryAlterableInterface
-   *   The called object.
-   */
-  public function addMetaData($key, $object);
-
-  /**
-   * Retrieves a given piece of metadata.
-   *
-   * @param $key
-   *   The unique identifier for the piece of metadata to retrieve.
-   *
-   * @return
-   *   The previously attached metadata object, or NULL if one doesn't exist.
-   */
-  public function getMetaData($key);
-}
-
-/**
- * Interface for a query that accepts placeholders.
- */
-interface QueryPlaceholderInterface {
-
-  /**
-   * Returns a unique identifier for this object.
-   */
-  public function uniqueIdentifier();
-
-  /**
-   * Returns the next placeholder ID for the query.
-   *
-   * @return
-   *   The next available placeholder ID as an integer.
-   */
-  public function nextPlaceholder();
-}
-
-/**
- * Base class for query builders.
- *
- * Note that query builders use PHP's magic __toString() method to compile the
- * query object into a prepared statement.
- */
-abstract class Query implements QueryPlaceholderInterface {
-
-  /**
-   * The connection object on which to run this query.
-   *
-   * @var DatabaseConnection
-   */
-  protected $connection;
-
-  /**
-   * The target of the connection object.
-   * 
-   * @var string
-   */
-  protected $connectionTarget;
-
-  /**
-   * The key of the connection object.
-   * 
-   * @var string
-   */
-  protected $connectionKey;
-
-  /**
-   * The query options to pass on to the connection object.
-   *
-   * @var array
-   */
-  protected $queryOptions;
-
-  /**
-   * A unique identifier for this query object.
-   */
-  protected $uniqueIdentifier;
-
-  /**
-   * The placeholder counter.
-   */
-  protected $nextPlaceholder = 0;
-
-  /**
-   * An array of comments that can be prepended to a query.
-   *
-   * @var array
-   */
-  protected $comments = array();
-
-  /**
-   * Constructs a Query object.
-   *
-   * @param DatabaseConnection $connection
-   *   Database connection object.
-   * @param array $options
-   *   Array of query options.
-   */
-  public function __construct(DatabaseConnection $connection, $options) {
-    $this->uniqueIdentifier = uniqid('', TRUE);
-
-    $this->connection = $connection;
-    $this->connectionKey = $this->connection->getKey();
-    $this->connectionTarget = $this->connection->getTarget();
-
-    $this->queryOptions = $options;
-  }
-
-  /**
-   * Implements the magic __sleep function to disconnect from the database.
-   */
-  public function __sleep() {
-    $keys = get_object_vars($this);
-    unset($keys['connection']);
-    return array_keys($keys);
-  }
-
-  /**
-   * Implements the magic __wakeup function to reconnect to the database.
-   */
-  public function __wakeup() {
-    $this->connection = Database::getConnection($this->connectionTarget, $this->connectionKey);
-  }
-
-  /**
-   * Implements the magic __clone function.
-   */
-  public function __clone() {
-    $this->uniqueIdentifier = uniqid('', TRUE);
-  }
-
-  /**
-   * Runs the query against the database.
-   */
-  abstract protected function execute();
-
-  /**
-   * Implements PHP magic __toString method to convert the query to a string.
-   *
-   * The toString operation is how we compile a query object to a prepared
-   * statement.
-   *
-   * @return
-   *   A prepared statement query string for this object.
-   */
-  abstract public function __toString();
-
-  /**
-   * Returns a unique identifier for this object.
-   */
-  public function uniqueIdentifier() {
-    return $this->uniqueIdentifier;
-  }
-
-  /**
-   * Gets the next placeholder value for this query object.
-   *
-   * @return int
-   *   Next placeholder value.
-   */
-  public function nextPlaceholder() {
-    return $this->nextPlaceholder++;
-  }
-
-  /**
-   * Adds a comment to the query.
-   *
-   * By adding a comment to a query, you can more easily find it in your
-   * query log or the list of active queries on an SQL server. This allows
-   * for easier debugging and allows you to more easily find where a query
-   * with a performance problem is being generated.
-   *
-   * The comment string will be sanitized to remove * / and other characters
-   * that may terminate the string early so as to avoid SQL injection attacks.
-   *
-   * @param $comment
-   *   The comment string to be inserted into the query.
-   *
-   * @return Query
-   *   The called object.
-   */
-  public function comment($comment) {
-    $this->comments[] = $comment;
-    return $this;
-  }
-
-  /**
-   * Returns a reference to the comments array for the query.
-   *
-   * Because this method returns by reference, alter hooks may edit the comments
-   * array directly to make their changes. If just adding comments, however, the
-   * use of comment() is preferred.
-   *
-   * Note that this method must be called by reference as well:
-   * @code
-   * $comments =& $query->getComments();
-   * @endcode
-   *
-   * @return
-   *   A reference to the comments array structure.
-   */
-  public function &getComments() {
-    return $this->comments;
-  }
-}
-
-/**
- * General class for an abstracted INSERT query.
- */
-class InsertQuery extends Query {
-
-  /**
-   * The table on which to insert.
-   *
-   * @var string
-   */
-  protected $table;
-
-  /**
-   * An array of fields on which to insert.
-   *
-   * @var array
-   */
-  protected $insertFields = array();
-
-  /**
-   * An array of fields that should be set to their database-defined defaults.
-   *
-   * @var array
-   */
-  protected $defaultFields = array();
-
-  /**
-   * A nested array of values to insert.
-   *
-   * $insertValues is an array of arrays. Each sub-array is either an
-   * associative array whose keys are field names and whose values are field
-   * values to insert, or a non-associative array of values in the same order
-   * as $insertFields.
-   *
-   * Whether multiple insert sets will be run in a single query or multiple
-   * queries is left to individual drivers to implement in whatever manner is
-   * most appropriate. The order of values in each sub-array must match the
-   * order of fields in $insertFields.
-   *
-   * @var array
-   */
-  protected $insertValues = array();
-
-  /**
-   * A SelectQuery object to fetch the rows that should be inserted.
-   *
-   * @var SelectQueryInterface
-   */
-  protected $fromQuery;
-
-  /**
-   * Constructs an InsertQuery object.
-   *
-   * @param DatabaseConnection $connection
-   *   A DatabaseConnection object.
-   * @param string $table
-   *   Name of the table to associate with this query.
-   * @param array $options
-   *   Array of database options.
-   */
-  public function __construct($connection, $table, array $options = array()) {
-    if (!isset($options['return'])) {
-      $options['return'] = Database::RETURN_INSERT_ID;
-    }
-    parent::__construct($connection, $options);
-    $this->table = $table;
-  }
-
-  /**
-   * Adds a set of field->value pairs to be inserted.
-   *
-   * This method may only be called once. Calling it a second time will be
-   * ignored. To queue up multiple sets of values to be inserted at once,
-   * use the values() method.
-   *
-   * @param $fields
-   *   An array of fields on which to insert. This array may be indexed or
-   *   associative. If indexed, the array is taken to be the list of fields.
-   *   If associative, the keys of the array are taken to be the fields and
-   *   the values are taken to be corresponding values to insert. If a
-   *   $values argument is provided, $fields must be indexed.
-   * @param $values
-   *   An array of fields to insert into the database. The values must be
-   *   specified in the same order as the $fields array.
-   *
-   * @return InsertQuery
-   *   The called object.
-   */
-  public function fields(array $fields, array $values = array()) {
-    if (empty($this->insertFields)) {
-      if (empty($values)) {
-        if (!is_numeric(key($fields))) {
-          $values = array_values($fields);
-          $fields = array_keys($fields);
-        }
-      }
-      $this->insertFields = $fields;
-      if (!empty($values)) {
-        $this->insertValues[] = $values;
-      }
-    }
-
-    return $this;
-  }
-
-  /**
-   * Adds another set of values to the query to be inserted.
-   *
-   * If $values is a numeric-keyed array, it will be assumed to be in the same
-   * order as the original fields() call. If it is associative, it may be
-   * in any order as long as the keys of the array match the names of the
-   * fields.
-   *
-   * @param $values
-   *   An array of values to add to the query.
-   *
-   * @return InsertQuery
-   *   The called object.
-   */
-  public function values(array $values) {
-    if (is_numeric(key($values))) {
-      $this->insertValues[] = $values;
-    }
-    else {
-      // Reorder the submitted values to match the fields array.
-      foreach ($this->insertFields as $key) {
-        $insert_values[$key] = $values[$key];
-      }
-      // For consistency, the values array is always numerically indexed.
-      $this->insertValues[] = array_values($insert_values);
-    }
-    return $this;
-  }
-
-  /**
-   * Specifies fields for which the database defaults should be used.
-   *
-   * If you want to force a given field to use the database-defined default,
-   * not NULL or undefined, use this method to instruct the database to use
-   * default values explicitly. In most cases this will not be necessary
-   * unless you are inserting a row that is all default values, as you cannot
-   * specify no values in an INSERT query.
-   *
-   * Specifying a field both in fields() and in useDefaults() is an error
-   * and will not execute.
-   *
-   * @param $fields
-   *   An array of values for which to use the default values
-   *   specified in the table definition.
-   *
-   * @return InsertQuery
-   *   The called object.
-   */
-  public function useDefaults(array $fields) {
-    $this->defaultFields = $fields;
-    return $this;
-  }
-
-  /**
-   * Sets the fromQuery on this InsertQuery object.
-   *
-   * @param SelectQueryInterface $query
-   *   The query to fetch the rows that should be inserted.
-   *
-   * @return InsertQuery
-   *   The called object.
-   */
-  public function from(SelectQueryInterface $query) {
-    $this->fromQuery = $query;
-    return $this;
-  }
-
-  /**
-   * Executes the insert query.
-   *
-   * @return
-   *   The last insert ID of the query, if one exists. If the query
-   *   was given multiple sets of values to insert, the return value is
-   *   undefined. If no fields are specified, this method will do nothing and
-   *   return NULL. That makes it safe to use in multi-insert loops.
-   */
-  public function execute() {
-    // If validation fails, simply return NULL. Note that validation routines
-    // in preExecute() may throw exceptions instead.
-    if (!$this->preExecute()) {
-      return NULL;
-    }
-
-    // If we're selecting from a SelectQuery, finish building the query and
-    // pass it back, as any remaining options are irrelevant.
-    if (!empty($this->fromQuery)) {
-      $sql = (string) $this;
-      // The SelectQuery may contain arguments, load and pass them through.
-      return $this->connection->query($sql, $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
-    // databases, such as SQLite, this is also a notable performance boost.
-    $transaction = $this->connection->startTransaction();
-
-    try {
-      $sql = (string) $this;
-      foreach ($this->insertValues as $insert_values) {
-        $last_insert_id = $this->connection->query($sql, $insert_values, $this->queryOptions);
-      }
-    }
-    catch (Exception $e) {
-      // One of the INSERTs failed, rollback the whole batch.
-      $transaction->rollback();
-      // Rethrow the exception for the calling code.
-      throw $e;
-    }
-
-    // Re-initialize the values array so that we can re-use this query.
-    $this->insertValues = array();
-
-    // Transaction commits here where $transaction looses scope.
-
-    return $last_insert_id;
-  }
-
-  /**
-   * Implements PHP magic __toString method to convert the query to a string.
-   *
-   * @return string
-   *   The prepared statement.
-   */
-  public function __toString() {
-    // Create a sanitized comment string to prepend to the query.
-    $comments = $this->connection->makeComment($this->comments);
-
-    // Default fields are always placed first for consistency.
-    $insert_fields = array_merge($this->defaultFields, $this->insertFields);
-
-    if (!empty($this->fromQuery)) {
-      return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') ' . $this->fromQuery;
-    }
-
-    // For simplicity, we will use the $placeholders array to inject
-    // default keywords even though they are not, strictly speaking,
-    // placeholders for prepared statements.
-    $placeholders = array();
-    $placeholders = array_pad($placeholders, count($this->defaultFields), 'default');
-    $placeholders = array_pad($placeholders, count($this->insertFields), '?');
-
-    return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES (' . implode(', ', $placeholders) . ')';
-  }
-
-  /**
-   * Preprocesses and validates the query.
-   *
-   * @return
-   *   TRUE if the validation was successful, FALSE if not.
-   *
-   * @throws FieldsOverlapException
-   * @throws NoFieldsException
-   */
-  public function preExecute() {
-    // Confirm that the user did not try to specify an identical
-    // field and default field.
-    if (array_intersect($this->insertFields, $this->defaultFields)) {
-      throw new FieldsOverlapException('You may not specify the same field to have a value and a schema-default value.');
-    }
-
-    if (!empty($this->fromQuery)) {
-      // We have to assume that the used aliases match the insert fields.
-      // Regular fields are added to the query before expressions, maintain the
-      // same order for the insert fields.
-      // This behavior can be overridden by calling fields() manually as only the
-      // first call to fields() does have an effect.
-      $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) {
-      throw new NoFieldsException('There are no fields available to insert with.');
-    }
-
-    // If no values have been added, silently ignore this query. This can happen
-    // if values are added conditionally, so we don't want to throw an
-    // exception.
-    if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
-      return FALSE;
-    }
-    return TRUE;
-  }
-}
-
-/**
- * General class for an abstracted DELETE operation.
- */
-class DeleteQuery extends Query implements QueryConditionInterface {
-
-  /**
-   * The table from which to delete.
-   *
-   * @var string
-   */
-  protected $table;
-
-  /**
-   * The condition object for this query.
-   *
-   * Condition handling is handled via composition.
-   *
-   * @var DatabaseCondition
-   */
-  protected $condition;
-
-  /**
-   * Constructs a DeleteQuery object.
-   *
-   * @param DatabaseConnection $connection
-   *   A DatabaseConnection object.
-   * @param string $table
-   *   Name of the table to associate with this query.
-   * @param array $options
-   *   Array of database options.
-   */
-  public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
-    $options['return'] = Database::RETURN_AFFECTED;
-    parent::__construct($connection, $options);
-    $this->table = $table;
-
-    $this->condition = new DatabaseCondition('AND');
-  }
-
-  /**
-   * Implements QueryConditionInterface::condition().
-   */
-  public function condition($field, $value = NULL, $operator = NULL) {
-    $this->condition->condition($field, $value, $operator);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::isNull().
-   */
-  public function isNull($field) {
-    $this->condition->isNull($field);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::isNotNull().
-   */
-  public function isNotNull($field) {
-    $this->condition->isNotNull($field);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::exists().
-   */
-  public function exists(SelectQueryInterface $select) {
-    $this->condition->exists($select);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::notExists().
-   */
-  public function notExists(SelectQueryInterface $select) {
-    $this->condition->notExists($select);
-    return $this;
-  }
-  
-  /**
-   * Implements QueryConditionInterface::conditions().
-   */
-  public function &conditions() {
-    return $this->condition->conditions();
-  }
-
-  /**
-   * Implements QueryConditionInterface::arguments().
-   */
-  public function arguments() {
-    return $this->condition->arguments();
-  }
-
-  /**
-   * Implements QueryConditionInterface::where().
-   */
-  public function where($snippet, $args = array()) {
-    $this->condition->where($snippet, $args);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::compile().
-   */
-  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
-    return $this->condition->compile($connection, $queryPlaceholder);
-  }
-
-  /**
-   * Implements QueryConditionInterface::compiled().
-   */
-  public function compiled() {
-    return $this->condition->compiled();
-  }
-
-  /**
-   * Executes the DELETE query.
-   *
-   * @return
-   *   The return value is dependent on the database connection.
-   */
-  public function execute() {
-    $values = array();
-    if (count($this->condition)) {
-      $this->condition->compile($this->connection, $this);
-      $values = $this->condition->arguments();
-    }
-
-    return $this->connection->query((string) $this, $values, $this->queryOptions);
-  }
-
-  /**
-   * Implements PHP magic __toString method to convert the query to a string.
-   *
-   * @return string
-   *   The prepared statement.
-   */
-  public function __toString() {
-    // Create a sanitized comment string to prepend to the query.
-    $comments = $this->connection->makeComment($this->comments);
-
-    $query = $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '} ';
-
-    if (count($this->condition)) {
-
-      $this->condition->compile($this->connection, $this);
-      $query .= "\nWHERE " . $this->condition;
-    }
-
-    return $query;
-  }
-}
-
-
-/**
- * General class for an abstracted TRUNCATE operation.
- */
-class TruncateQuery extends Query {
-
-  /**
-   * The table to truncate.
-   *
-   * @var string
-   */
-  protected $table;
-
-  /**
-   * Constructs a TruncateQuery object.
-   *
-   * @param DatabaseConnection $connection
-   *   A DatabaseConnection object.
-   * @param string $table
-   *   Name of the table to associate with this query.
-   * @param array $options
-   *   Array of database options.
-   */
-  public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
-    $options['return'] = Database::RETURN_AFFECTED;
-    parent::__construct($connection, $options);
-    $this->table = $table;
-  }
-
-  /**
-   * Implements QueryConditionInterface::compile().
-   */
-  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
-    return $this->condition->compile($connection, $queryPlaceholder);
-  }
-
-  /**
-   * Implements QueryConditionInterface::compiled().
-   */
-  public function compiled() {
-    return $this->condition->compiled();
-  }
-
-  /**
-   * Executes the TRUNCATE query.
-   *
-   * @return
-   *   Return value is dependent on the database type.
-   */
-  public function execute() {
-    return $this->connection->query((string) $this, array(), $this->queryOptions);
-  }
-
-  /**
-   * Implements PHP magic __toString method to convert the query to a string.
-   *
-   * @return string
-   *   The prepared statement.
-   */
-  public function __toString() {
-    // Create a sanitized comment string to prepend to the query.
-    $comments = $this->connection->makeComment($this->comments);
-
-    return $comments . 'TRUNCATE {' . $this->connection->escapeTable($this->table) . '} ';
-  }
-}
-
-/**
- * General class for an abstracted UPDATE operation.
- */
-class UpdateQuery extends Query implements QueryConditionInterface {
-
-  /**
-   * The table to update.
-   *
-   * @var string
-   */
-  protected $table;
-
-  /**
-   * An array of fields that will be updated.
-   *
-   * @var array
-   */
-  protected $fields = array();
-
-  /**
-   * An array of values to update to.
-   *
-   * @var array
-   */
-  protected $arguments = array();
-
-  /**
-   * The condition object for this query.
-   *
-   * Condition handling is handled via composition.
-   *
-   * @var DatabaseCondition
-   */
-  protected $condition;
-
-  /**
-   * Array of fields to update to an expression in case of a duplicate record.
-   *
-   * This variable is a nested array in the following format:
-   * @code
-   * <some field> => array(
-   *  'condition' => <condition to execute, as a string>,
-   *  'arguments' => <array of arguments for condition, or NULL for none>,
-   * );
-   * @endcode
-   *
-   * @var array
-   */
-  protected $expressionFields = array();
-
-  /**
-   * Constructs an UpdateQuery object.
-   *
-   * @param DatabaseConnection $connection
-   *   A DatabaseConnection object.
-   * @param string $table
-   *   Name of the table to associate with this query.
-   * @param array $options
-   *   Array of database options.
-   */
-  public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
-    $options['return'] = Database::RETURN_AFFECTED;
-    parent::__construct($connection, $options);
-    $this->table = $table;
-
-    $this->condition = new DatabaseCondition('AND');
-  }
-
-  /**
-   * Implements QueryConditionInterface::condition().
-   */
-  public function condition($field, $value = NULL, $operator = NULL) {
-    $this->condition->condition($field, $value, $operator);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::isNull().
-   */
-  public function isNull($field) {
-    $this->condition->isNull($field);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::isNotNull().
-   */
-  public function isNotNull($field) {
-    $this->condition->isNotNull($field);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::exists().
-   */
-  public function exists(SelectQueryInterface $select) {
-    $this->condition->exists($select);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::notExists().
-   */
-  public function notExists(SelectQueryInterface $select) {
-    $this->condition->notExists($select);
-    return $this;
-  }
-  
-  /**
-   * Implements QueryConditionInterface::conditions().
-   */
-  public function &conditions() {
-    return $this->condition->conditions();
-  }
-
-  /**
-   * Implements QueryConditionInterface::arguments().
-   */
-  public function arguments() {
-    return $this->condition->arguments();
-  }
-
-  /**
-   * Implements QueryConditionInterface::where().
-   */
-  public function where($snippet, $args = array()) {
-    $this->condition->where($snippet, $args);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::compile().
-   */
-  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
-    return $this->condition->compile($connection, $queryPlaceholder);
-  }
-
-  /**
-   * Implements QueryConditionInterface::compiled().
-   */
-  public function compiled() {
-    return $this->condition->compiled();
-  }
-
-  /**
-   * Adds a set of field->value pairs to be updated.
-   *
-   * @param $fields
-   *   An associative array of fields to write into the database. The array keys
-   *   are the field names and the values are the values to which to set them.
-   *
-   * @return UpdateQuery
-   *   The called object.
-   */
-  public function fields(array $fields) {
-    $this->fields = $fields;
-    return $this;
-  }
-
-  /**
-   * Specifies fields to be updated as an expression.
-   *
-   * Expression fields are cases such as counter=counter+1. This method takes
-   * precedence over fields().
-   *
-   * @param $field
-   *   The field to set.
-   * @param $expression
-   *   The field will be set to the value of this expression. This parameter
-   *   may include named placeholders.
-   * @param $arguments
-   *   If specified, this is an array of key/value pairs for named placeholders
-   *   corresponding to the expression.
-   *
-   * @return UpdateQuery
-   *   The called object.
-   */
-  public function expression($field, $expression, array $arguments = NULL) {
-    $this->expressionFields[$field] = array(
-      'expression' => $expression,
-      'arguments' => $arguments,
-    );
-
-    return $this;
-  }
-
-  /**
-   * Executes the UPDATE query.
-   *
-   * @return
-   *   The number of rows affected by the update.
-   */
-  public function execute() {
-
-    // Expressions take priority over literal fields, so we process those first
-    // and remove any literal fields that conflict.
-    $fields = $this->fields;
-    $update_values = array();
-    foreach ($this->expressionFields as $field => $data) {
-      if (!empty($data['arguments'])) {
-        $update_values += $data['arguments'];
-      }
-      unset($fields[$field]);
-    }
-
-    // Because we filter $fields the same way here and in __toString(), the
-    // placeholders will all match up properly.
-    $max_placeholder = 0;
-    foreach ($fields as $field => $value) {
-      $update_values[':db_update_placeholder_' . ($max_placeholder++)] = $value;
-    }
-
-    if (count($this->condition)) {
-      $this->condition->compile($this->connection, $this);
-      $update_values = array_merge($update_values, $this->condition->arguments());
-    }
-
-    return $this->connection->query((string) $this, $update_values, $this->queryOptions);
-  }
-
-  /**
-   * Implements PHP magic __toString method to convert the query to a string.
-   *
-   * @return string
-   *   The prepared statement.
-   */
-  public function __toString() {
-    // Create a sanitized comment string to prepend to the query.
-    $comments = $this->connection->makeComment($this->comments);
-
-    // Expressions take priority over literal fields, so we process those first
-    // and remove any literal fields that conflict.
-    $fields = $this->fields;
-    $update_fields = array();
-    foreach ($this->expressionFields as $field => $data) {
-      $update_fields[] = $field . '=' . $data['expression'];
-      unset($fields[$field]);
-    }
-
-    $max_placeholder = 0;
-    foreach ($fields as $field => $value) {
-      $update_fields[] = $field . '=:db_update_placeholder_' . ($max_placeholder++);
-    }
-
-    $query = $comments . 'UPDATE {' . $this->connection->escapeTable($this->table) . '} SET ' . implode(', ', $update_fields);
-
-    if (count($this->condition)) {
-      $this->condition->compile($this->connection, $this);
-      // There is an implicit string cast on $this->condition.
-      $query .= "\nWHERE " . $this->condition;
-    }
-
-    return $query;
-  }
-
-}
-
-/**
- * General class for an abstracted MERGE query operation.
- *
- * An ANSI SQL:2003 compatible database would run the following query:
- *
- * @code
- * MERGE INTO table_name_1 USING table_name_2 ON (condition)
- *   WHEN MATCHED THEN
- *   UPDATE SET column1 = value1 [, column2 = value2 ...]
- *   WHEN NOT MATCHED THEN
- *   INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...
- * @endcode
- *
- * Other databases (most notably MySQL, PostgreSQL and SQLite) will emulate
- * this statement by running a SELECT and then INSERT or UPDATE.
- *
- * By default, the two table names are identical and they are passed into the
- * the constructor. table_name_2 can be specified by the
- * MergeQuery::conditionTable() method. It can be either a string or a
- * subquery.
- *
- * The condition is built exactly like SelectQuery or UpdateQuery conditions,
- * the UPDATE query part is built similarly like an UpdateQuery and finally the
- * INSERT query part is built similarly like an InsertQuery. However, both
- * UpdateQuery and InsertQuery has a fields method so
- * MergeQuery::updateFields() and MergeQuery::insertFields() needs to be called
- * instead. MergeQuery::fields() can also be called which calls both of these
- * methods as the common case is to use the same column-value pairs for both
- * INSERT and UPDATE. However, this is not mandatory. Another convinient
- * wrapper is MergeQuery::key() which adds the same column-value pairs to the
- * condition and the INSERT query part.
- *
- * Several methods (key(), fields(), insertFields()) can be called to set a
- * key-value pair for the INSERT query part. Subsequent calls for the same
- * fields override the earlier ones. The same is true for UPDATE and key(),
- * fields() and updateFields().
- */
-class MergeQuery extends Query implements QueryConditionInterface {
-  /**
-   * Returned by execute() if an INSERT query has been executed.
-   */
-  const STATUS_INSERT = 1;
-
-  /**
-   * Returned by execute() if an UPDATE query has been executed.
-   */
-  const STATUS_UPDATE = 2;
-
-  /**
-   * The table to be used for INSERT and UPDATE.
-   *
-   * @var string
-   */
-  protected $table;
-
-  /**
-   * The table or subquery to be used for the condition.
-   */
-  protected $conditionTable;
-
-  /**
-   * An array of fields on which to insert.
-   *
-   * @var array
-   */
-  protected $insertFields = array();
-
-  /**
-   * An array of fields which should be set to their database-defined defaults.
-   *
-   * Used on INSERT.
-   *
-   * @var array
-   */
-  protected $defaultFields = array();
-
-  /**
-   * An array of values to be inserted.
-   *
-   * @var string
-   */
-  protected $insertValues = array();
-
-  /**
-   * An array of fields that will be updated.
-   *
-   * @var array
-   */
-  protected $updateFields = array();
-
-  /**
-   * Array of fields to update to an expression in case of a duplicate record.
-   *
-   * This variable is a nested array in the following format:
-   * @code
-   * <some field> => array(
-   *  'condition' => <condition to execute, as a string>,
-   *  'arguments' => <array of arguments for condition, or NULL for none>,
-   * );
-   * @endcode
-   *
-   * @var array
-   */
-  protected $expressionFields = array();
-
-  /**
-   * Flag indicating whether an UPDATE is necessary.
-   *
-   * @var boolean
-   */
-  protected $needsUpdate = FALSE;
-
-  /**
-  * Constructs a MergeQuery object.
-  *
-  * @param DatabaseConnection $connection
-  *   A DatabaseConnection object.
-  * @param string $table
-  *   Name of the table to associate with this query.
-  * @param array $options
-  *   Array of database options.
-  */
-  public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
-    $options['return'] = Database::RETURN_AFFECTED;
-    parent::__construct($connection, $options);
-    $this->table = $table;
-    $this->conditionTable = $table;
-    $this->condition = new DatabaseCondition('AND');
-  }
-
-  /**
-   * Sets the table or subquery to be used for the condition.
-   *
-   * @param $table
-   *   The table name or the subquery to be used. Use a SelectQuery object to
-   *   pass in a subquery.
-   *
-   * @return MergeQuery
-   *   The called object.
-   */
-  protected function conditionTable($table) {
-    $this->conditionTable = $table;
-    return $this;
-  }
-
-  /**
-   * Adds a set of field->value pairs to be updated.
-   *
-   * @param $fields
-   *   An associative array of fields to write into the database. The array keys
-   *   are the field names and the values are the values to which to set them.
-   *
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function updateFields(array $fields) {
-    $this->updateFields = $fields;
-    $this->needsUpdate = TRUE;
-    return $this;
-  }
-
-  /**
-   * Specifies fields to be updated as an expression.
-   *
-   * Expression fields are cases such as counter = counter + 1. This method
-   * takes precedence over MergeQuery::updateFields() and it's wrappers,
-   * MergeQuery::key() and MergeQuery::fields().
-   *
-   * @param $field
-   *   The field to set.
-   * @param $expression
-   *   The field will be set to the value of this expression. This parameter
-   *   may include named placeholders.
-   * @param $arguments
-   *   If specified, this is an array of key/value pairs for named placeholders
-   *   corresponding to the expression.
-   *
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function expression($field, $expression, array $arguments = NULL) {
-    $this->expressionFields[$field] = array(
-      'expression' => $expression,
-      'arguments' => $arguments,
-    );
-    $this->needsUpdate = TRUE;
-    return $this;
-  }
-
-  /**
-   * Adds a set of field->value pairs to be inserted.
-   *
-   * @param $fields
-   *   An array of fields on which to insert. This array may be indexed or
-   *   associative. If indexed, the array is taken to be the list of fields.
-   *   If associative, the keys of the array are taken to be the fields and
-   *   the values are taken to be corresponding values to insert. If a
-   *   $values argument is provided, $fields must be indexed.
-   * @param $values
-   *   An array of fields to insert into the database. The values must be
-   *   specified in the same order as the $fields array.
-   *
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function insertFields(array $fields, array $values = array()) {
-    if ($values) {
-      $fields = array_combine($fields, $values);
-    }
-    $this->insertFields = $fields;
-    return $this;
-  }
-
-  /**
-   * Specifies fields for which the database-defaults should be used.
-   *
-   * If you want to force a given field to use the database-defined default,
-   * not NULL or undefined, use this method to instruct the database to use
-   * default values explicitly. In most cases this will not be necessary
-   * unless you are inserting a row that is all default values, as you cannot
-   * specify no values in an INSERT query.
-   *
-   * Specifying a field both in fields() and in useDefaults() is an error
-   * and will not execute.
-   *
-   * @param $fields
-   *   An array of values for which to use the default values
-   *   specified in the table definition.
-   *
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function useDefaults(array $fields) {
-    $this->defaultFields = $fields;
-    return $this;
-  }
-
-  /**
-   * Sets common field-value pairs in the INSERT and UPDATE query parts.
-   *
-   * This method should only be called once. It may be called either
-   * with a single associative array or two indexed arrays. If called
-   * with an associative array, the keys are taken to be the fields
-   * and the values are taken to be the corresponding values to set.
-   * If called with two arrays, the first array is taken as the fields
-   * and the second array is taken as the corresponding values.
-   *
-   * @param $fields
-   *   An array of fields to insert, or an associative array of fields and
-   *   values. The keys of the array are taken to be the fields and the values
-   *   are taken to be corresponding values to insert.
-   * @param $values
-   *   An array of values to set into the database. The values must be
-   *   specified in the same order as the $fields array.
-   *
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function fields(array $fields, array $values = array()) {
-    if ($values) {
-      $fields = array_combine($fields, $values);
-    }
-    foreach ($fields as $key => $value) {
-      $this->insertFields[$key] = $value;
-      $this->updateFields[$key] = $value;
-    }
-    $this->needsUpdate = TRUE;
-    return $this;
-  }
-
-  /**
-   * Sets the key field(s) to be used as conditions for this query.
-   *
-   * This method should only be called once. It may be called either
-   * with a single associative array or two indexed arrays. If called
-   * with an associative array, the keys are taken to be the fields
-   * and the values are taken to be the corresponding values to set.
-   * If called with two arrays, the first array is taken as the fields
-   * and the second array is taken as the corresponding values.
-   *
-   * The fields are copied to the condition of the query and the INSERT part.
-   * If no other method is called, the UPDATE will become a no-op.
-   *
-   * @param $fields
-   *   An array of fields to set, or an associative array of fields and values.
-   * @param $values
-   *   An array of values to set into the database. The values must be
-   *   specified in the same order as the $fields array.
-   *
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function key(array $fields, array $values = array()) {
-    if ($values) {
-      $fields = array_combine($fields, $values);
-    }
-    foreach ($fields as $key => $value) {
-      $this->insertFields[$key] = $value;
-      $this->condition($key, $value);
-    }
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::condition().
-   */
-  public function condition($field, $value = NULL, $operator = NULL) {
-    $this->condition->condition($field, $value, $operator);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::isNull().
-   */
-  public function isNull($field) {
-    $this->condition->isNull($field);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::isNotNull().
-   */
-  public function isNotNull($field) {
-    $this->condition->isNotNull($field);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::exists().
-   */
-  public function exists(SelectQueryInterface $select) {
-    $this->condition->exists($select);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::notExists().
-   */
-  public function notExists(SelectQueryInterface $select) {
-    $this->condition->notExists($select);
-    return $this;
-  }
-  
-  /**
-   * Implements QueryConditionInterface::conditions().
-   */
-  public function &conditions() {
-    return $this->condition->conditions();
-  }
-
-  /**
-   * Implements QueryConditionInterface::arguments().
-   */
-  public function arguments() {
-    return $this->condition->arguments();
-  }
-
-  /**
-   * Implements QueryConditionInterface::where().
-   */
-  public function where($snippet, $args = array()) {
-    $this->condition->where($snippet, $args);
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::compile().
-   */
-  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
-    return $this->condition->compile($connection, $queryPlaceholder);
-  }
-
-  /**
-   * Implements QueryConditionInterface::compiled().
-   */
-  public function compiled() {
-    return $this->condition->compiled();
-  }
-
-  /**
-   * Implements PHP magic __toString method to convert the query to a string.
-   *
-   * In the degenerate case, there is no string-able query as this operation
-   * is potentially two queries.
-   *
-   * @return string
-   *   The prepared query statement.
-   */
-  public function __toString() {
-  }
-
-  public function execute() {
-    // Wrap multiple queries in a transaction, if the database supports it.
-    $transaction = $this->connection->startTransaction();
-    try {
-      if (!count($this->condition)) {
-        throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
-      }
-      $select = $this->connection->select($this->conditionTable)
-        ->condition($this->condition)
-        ->forUpdate();
-      $select->addExpression('1');
-      if (!$select->execute()->fetchField()) {
-        try {
-          $insert = $this->connection->insert($this->table)->fields($this->insertFields);
-          if ($this->defaultFields) {
-            $insert->useDefaults($this->defaultFields);
-          }
-          $insert->execute();
-          return MergeQuery::STATUS_INSERT;
-        }
-        catch (Exception $e) {
-          // The insert query failed, maybe it's because a racing insert query
-          // beat us in inserting the same row. Retry the select query, if it
-          // returns a row, ignore the error and continue with the update
-          // query below.
-          if (!$select->execute()->fetchField()) {
-            throw $e;
-          }
-        }
-      }
-      if ($this->needsUpdate) {
-        $update = $this->connection->update($this->table)
-          ->fields($this->updateFields)
-          ->condition($this->condition);
-        if ($this->expressionFields) {
-          foreach ($this->expressionFields as $field => $data) {
-            $update->expression($field, $data['expression'], $data['arguments']);
-          }
-        }
-        $update->execute();
-        return MergeQuery::STATUS_UPDATE;
-      }
-    }
-    catch (Exception $e) {
-      // Something really wrong happened here, bubble up the exception to the
-      // caller.
-      $transaction->rollback();
-      throw $e;
-    }
-    // Transaction commits here where $transaction looses scope.
-  }
-}
-
-/**
- * Generic class for a series of conditions in a query.
- */
-class DatabaseCondition implements QueryConditionInterface, Countable {
-
-  /**
-   * Array of conditions.
-   *
-   * @var array
-   */
-  protected $conditions = array();
-
-  /**
-   * Array of arguments.
-   *
-   * @var array
-   */
-  protected $arguments = array();
-
-  /**
-   * Whether the conditions have been changed.
-   *
-   * TRUE if the condition has been changed since the last compile.
-   * FALSE if the condition has been compiled and not changed.
-   *
-   * @var bool
-   */
-  protected $changed = TRUE;
-
-  /**
-   * The identifier of the query placeholder this condition has been compiled against.
-   */
-  protected $queryPlaceholderIdentifier;
-
-  /**
-   * Constructs a DataBaseCondition object.
-   *
-   * @param string $conjunction
-   *   The operator to use to combine conditions: 'AND' or 'OR'.
-   */
-  public function __construct($conjunction) {
-    $this->conditions['#conjunction'] = $conjunction;
-  }
-
-  /**
-   * Implements Countable::count().
-   *
-   * Returns the size of this conditional. The size of the conditional is the
-   * size of its conditional array minus one, because one element is the the
-   * conjunction.
-   */
-  public function count() {
-    return count($this->conditions) - 1;
-  }
-
-  /**
-   * Implements QueryConditionInterface::condition().
-   */
-  public function condition($field, $value = NULL, $operator = NULL) {
-    if (!isset($operator)) {
-      if (is_array($value)) {
-        $operator = 'IN';
-      }
-      else {
-        $operator = '=';
-      }
-    }
-    $this->conditions[] = array(
-      'field' => $field,
-      'value' => $value,
-      'operator' => $operator,
-    );
-
-    $this->changed = TRUE;
-
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::where().
-   */
-  public function where($snippet, $args = array()) {
-    $this->conditions[] = array(
-      'field' => $snippet,
-      'value' => $args,
-      'operator' => NULL,
-    );
-    $this->changed = TRUE;
-
-    return $this;
-  }
-
-  /**
-   * Implements QueryConditionInterface::isNull().
-   */
-  public function isNull($field) {
-    return $this->condition($field, NULL, 'IS NULL');
-  }
-
-  /**
-   * Implements QueryConditionInterface::isNotNull().
-   */
-  public function isNotNull($field) {
-    return $this->condition($field, NULL, 'IS NOT NULL');
-  }
-
-  /**
-   * Implements QueryConditionInterface::exists().
-   */
-  public function exists(SelectQueryInterface $select) {
-    return $this->condition('', $select, 'EXISTS');
-  }
-  
-  /**
-   * Implements QueryConditionInterface::notExists().
-   */
-  public function notExists(SelectQueryInterface $select) {
-    return $this->condition('', $select, 'NOT EXISTS');
-  }
-  
-  /**
-   * Implements QueryConditionInterface::conditions().
-   */
-  public function &conditions() {
-    return $this->conditions;
-  }
-
-  /**
-   * Implements QueryConditionInterface::arguments().
-   */
-  public function arguments() {
-    // If the caller forgot to call compile() first, refuse to run.
-    if ($this->changed) {
-      return NULL;
-    }
-    return $this->arguments;
-  }
-
-  /**
-   * Implements QueryConditionInterface::compile().
-   */
-  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
-    // Re-compile if this condition changed or if we are compiled against a
-    // different query placeholder object.
-    if ($this->changed || isset($this->queryPlaceholderIdentifier) && ($this->queryPlaceholderIdentifier != $queryPlaceholder->uniqueIdentifier())) {
-      $this->queryPlaceholderIdentifier = $queryPlaceholder->uniqueIdentifier();
-
-      $condition_fragments = array();
-      $arguments = array();
-
-      $conditions = $this->conditions;
-      $conjunction = $conditions['#conjunction'];
-      unset($conditions['#conjunction']);
-      foreach ($conditions as $condition) {
-        if (empty($condition['operator'])) {
-          // This condition is a literal string, so let it through as is.
-          $condition_fragments[] = ' (' . $condition['field'] . ') ';
-          $arguments += $condition['value'];
-        }
-        else {
-          // It's a structured condition, so parse it out accordingly.
-          // Note that $condition['field'] will only be an object for a dependent
-          // DatabaseCondition object, not for a dependent subquery.
-          if ($condition['field'] instanceof QueryConditionInterface) {
-            // Compile the sub-condition recursively and add it to the list.
-            $condition['field']->compile($connection, $queryPlaceholder);
-            $condition_fragments[] = '(' . (string) $condition['field'] . ')';
-            $arguments += $condition['field']->arguments();
-          }
-          else {
-            // For simplicity, we treat all operators as the same data structure.
-            // In the typical degenerate case, this won't get changed.
-            $operator_defaults = array(
-              'prefix' => '',
-              'postfix' => '',
-              'delimiter' => '',
-              'operator' => $condition['operator'],
-              'use_value' => TRUE,
-            );
-            $operator = $connection->mapConditionOperator($condition['operator']);
-            if (!isset($operator)) {
-              $operator = $this->mapConditionOperator($condition['operator']);
-            }
-            $operator += $operator_defaults;
-
-            $placeholders = array();
-            if ($condition['value'] instanceof SelectQueryInterface) {
-              $condition['value']->compile($connection, $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;
-            }
-            // We assume that if there is a delimiter, then the value is an
-            // array. If not, it is a scalar. For simplicity, we first convert
-            // up to an array so that we can build the placeholders in the same way.
-            elseif (!$operator['delimiter']) {
-              $condition['value'] = array($condition['value']);
-            }
-            if ($operator['use_value']) {
-              foreach ($condition['value'] as $value) {
-                $placeholder = ':db_condition_placeholder_' . $queryPlaceholder->nextPlaceholder();
-                $arguments[$placeholder] = $value;
-                $placeholders[] = $placeholder;
-              }
-            }
-            $condition_fragments[] = ' (' . $connection->escapeField($condition['field']) . ' ' . $operator['operator'] . ' ' . $operator['prefix'] . implode($operator['delimiter'], $placeholders) . $operator['postfix'] . ') ';
-          }
-        }
-      }
-
-      $this->changed = FALSE;
-      $this->stringVersion = implode($conjunction, $condition_fragments);
-      $this->arguments = $arguments;
-    }
-  }
-
-  /**
-   * Implements QueryConditionInterface::compiled().
-   */
-  public function compiled() {
-    return !$this->changed;
-  }
-
-  /**
-   * Implements PHP magic __toString method to convert the conditions to string.
-   *
-   * @return string
-   *   A string version of the conditions.
-   */
-  public function __toString() {
-    // If the caller forgot to call compile() first, refuse to run.
-    if ($this->changed) {
-      return NULL;
-    }
-    return $this->stringVersion;
-  }
-
-  /**
-   * PHP magic __clone() method.
-   *
-   * Only copies fields that implement QueryConditionInterface. Also sets
-   * $this->changed to TRUE.
-   */
-  function __clone() {
-    $this->changed = TRUE;
-    foreach ($this->conditions as $key => $condition) {
-      if ($condition['field'] instanceOf QueryConditionInterface) {
-        $this->conditions[$key]['field'] = clone($condition['field']);
-      }
-    }
-  }
-
-  /**
-   * Gets any special processing requirements for the condition operator.
-   *
-   * Some condition types require special processing, such as IN, because
-   * the value data they pass in is not a simple value. This is a simple
-   * overridable lookup function.
-   *
-   * @param $operator
-   *   The condition operator, such as "IN", "BETWEEN", etc. Case-sensitive.
-   *
-   * @return
-   *   The extra handling directives for the specified operator, or NULL.
-   */
-  protected function mapConditionOperator($operator) {
-    // $specials does not use drupal_static as its value never changes.
-    static $specials = array(
-      'BETWEEN' => array('delimiter' => ' AND '),
-      'IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
-      'NOT IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
-      'EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
-      'NOT EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
-      'IS NULL' => array('use_value' => FALSE),
-      'IS NOT NULL' => array('use_value' => FALSE),
-      // Use backslash for escaping wildcard characters.
-      'LIKE' => array('postfix' => " ESCAPE '\\\\'"),
-      'NOT LIKE' => array('postfix' => " ESCAPE '\\\\'"),
-      // These ones are here for performance reasons.
-      '=' => array(),
-      '<' => array(),
-      '>' => array(),
-      '>=' => array(),
-      '<=' => array(),
-    );
-    if (isset($specials[$operator])) {
-      $return = $specials[$operator];
-    }
-    else {
-      // We need to upper case because PHP index matches are case sensitive but
-      // do not need the more expensive drupal_strtoupper because SQL statements are ASCII.
-      $operator = strtoupper($operator);
-      $return = isset($specials[$operator]) ? $specials[$operator] : array();
-    }
-
-    $return += array('operator' => $operator);
-
-    return $return;
-  }
-
-}
-
-/**
- * @} End of "ingroup database".
- */
diff --git a/core/includes/database/select.inc b/core/includes/database/select.inc
deleted file mode 100644
index 9bc6b92e1d908c0d97bef2976df4873867628d1f..0000000000000000000000000000000000000000
--- a/core/includes/database/select.inc
+++ /dev/null
@@ -1,1609 +0,0 @@
-<?php
-
-/**
- * @ingroup database
- * @{
- */
-
-require_once __DIR__ . '/query.inc';
-
-/**
- * Interface for extendable query objects.
- *
- * "Extenders" follow the "Decorator" OOP design pattern.  That is, they wrap
- * and "decorate" another object.  In our case, they implement the same interface
- * as select queries and wrap a select query, to which they delegate almost all
- * operations.  Subclasses of this class may implement additional methods or
- * override existing methods as appropriate.  Extenders may also wrap other
- * extender objects, allowing for arbitrarily complex "enhanced" queries.
- */
-interface QueryExtendableInterface {
-
-  /**
-   * Enhance this object by wrapping it in an extender object.
-   *
-   * @param $extender_name
-   *   The base name of the extending class.  The base name will be checked
-   *   against the current database connection to allow driver-specific subclasses
-   *   as well, using the same logic as the query objects themselves.  For example,
-   *   PagerDefault_mysql is the MySQL-specific override for PagerDefault.
-   * @return QueryExtendableInterface
-   *   The extender object, which now contains a reference to this object.
-   */
-  public function extend($extender_name);
-}
-
-/**
- * Interface definition for a Select Query object.
- */
-interface SelectQueryInterface extends QueryConditionInterface, QueryAlterableInterface, QueryExtendableInterface, QueryPlaceholderInterface {
-
-  /* Alter accessors to expose the query data to alter hooks. */
-
-  /**
-   * Returns a reference to the fields array for this query.
-   *
-   * Because this method returns by reference, alter hooks may edit the fields
-   * array directly to make their changes. If just adding fields, however, the
-   * use of addField() is preferred.
-   *
-   * Note that this method must be called by reference as well:
-   *
-   * @code
-   * $fields =& $query->getFields();
-   * @endcode
-   *
-   * @return
-   *   A reference to the fields array structure.
-   */
-  public function &getFields();
-
-  /**
-   * Returns a reference to the expressions array for this query.
-   *
-   * Because this method returns by reference, alter hooks may edit the expressions
-   * array directly to make their changes. If just adding expressions, however, the
-   * use of addExpression() is preferred.
-   *
-   * Note that this method must be called by reference as well:
-   *
-   * @code
-   * $fields =& $query->getExpressions();
-   * @endcode
-   *
-   * @return
-   *   A reference to the expression array structure.
-   */
-  public function &getExpressions();
-
-  /**
-   * Returns a reference to the order by array for this query.
-   *
-   * Because this method returns by reference, alter hooks may edit the order-by
-   * array directly to make their changes. If just adding additional ordering
-   * fields, however, the use of orderBy() is preferred.
-   *
-   * Note that this method must be called by reference as well:
-   *
-   * @code
-   * $fields =& $query->getOrderBy();
-   * @endcode
-   *
-   * @return
-   *   A reference to the expression array structure.
-   */
-  public function &getOrderBy();
-
-  /**
-   * Returns a reference to the group-by array for this query.
-   *
-   * Because this method returns by reference, alter hooks may edit the group-by
-   * array directly to make their changes. If just adding additional grouping
-   * fields, however, the use of groupBy() is preferred.
-   *
-   * Note that this method must be called by reference as well:
-   *
-   * @code
-   * $fields =& $query->getGroupBy();
-   * @endcode
-   *
-   * @return
-   *   A reference to the group-by array structure.
-   */
-  public function &getGroupBy();
-
-  /**
-   * Returns a reference to the tables array for this query.
-   *
-   * Because this method returns by reference, alter hooks may edit the tables
-   * array directly to make their changes. If just adding tables, however, the
-   * use of the join() methods is preferred.
-   *
-   * Note that this method must be called by reference as well:
-   *
-   * @code
-   * $fields =& $query->getTables();
-   * @endcode
-   *
-   * @return
-   *   A reference to the tables array structure.
-   */
-  public function &getTables();
-
-  /**
-   * Returns a reference to the union queries for this query. This include
-   * queries for UNION, UNION ALL, and UNION DISTINCT.
-   *
-   * Because this method returns by reference, alter hooks may edit the tables
-   * array directly to make their changes. If just adding union queries,
-   * however, the use of the union() method is preferred.
-   *
-   * Note that this method must be called by reference as well:
-   *
-   * @code
-   * $fields =& $query->getUnion();
-   * @endcode
-   *
-   * @return
-   *   A reference to the union query array structure.
-   */
-  public function &getUnion();
-
-  /**
-   * Compiles and returns an associative array of the arguments for this prepared statement.
-   *
-   * @param $queryPlaceholder
-   *   When collecting the arguments of a subquery, the main placeholder
-   *   object should be passed as this parameter.
-   *
-   * @return
-   *   An associative array of all placeholder arguments for this query.
-   */
-  public function getArguments(QueryPlaceholderInterface $queryPlaceholder = NULL);
-
-  /* Query building operations */
-
-  /**
-   * Sets this query to be DISTINCT.
-   *
-   * @param $distinct
-   *   TRUE to flag this query DISTINCT, FALSE to disable it.
-   * @return SelectQueryInterface
-   *   The called object.
-   */
-  public function distinct($distinct = TRUE);
-
-  /**
-   * Adds a field to the list to be SELECTed.
-   *
-   * @param $table_alias
-   *   The name of the table from which the field comes, as an alias. Generally
-   *   you will want to use the return value of join() here to ensure that it is
-   *   valid.
-   * @param $field
-   *   The name of the field.
-   * @param $alias
-   *   The alias for this field. If not specified, one will be generated
-   *   automatically based on the $table_alias and $field. The alias will be
-   *   checked for uniqueness, so the requested alias may not be the alias
-   *   that is assigned in all cases.
-   * @return
-   *   The unique alias that was assigned for this field.
-   */
-  public function addField($table_alias, $field, $alias = NULL);
-
-  /**
-   * Add multiple fields from the same table to be SELECTed.
-   *
-   * This method does not return the aliases set for the passed fields. In the
-   * majority of cases that is not a problem, as the alias will be the field
-   * name. However, if you do need to know the alias you can call getFields()
-   * and examine the result to determine what alias was created. Alternatively,
-   * simply use addField() for the few fields you care about and this method for
-   * the rest.
-   *
-   * @param $table_alias
-   *   The name of the table from which the field comes, as an alias. Generally
-   *   you will want to use the return value of join() here to ensure that it is
-   *   valid.
-   * @param $fields
-   *   An indexed array of fields present in the specified table that should be
-   *   included in this query. If not specified, $table_alias.* will be generated
-   *   without any aliases.
-   * @return SelectQueryInterface
-   *   The called object.
-   */
-  public function fields($table_alias, array $fields = 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
-   * various functions, which may in some cases be database-dependent. This
-   * method makes no effort to correct for database-specific functions.
-   *
-   * @param $expression
-   *   The expression string. May contain placeholders.
-   * @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 assigned
-   *   in all cases.
-   * @param $arguments
-   *   Any placeholder arguments needed for this expression.
-   * @return
-   *   The unique alias that was assigned for this expression.
-   */
-  public function addExpression($expression, $alias = NULL, $arguments = array());
-
-  /**
-   * Default Join against another table in the database.
-   *
-   * This method is a convenience method for innerJoin().
-   *
-   * @param $table
-   *   The table against which to join.
-   * @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.
-   * @param $condition
-   *   The condition on which to join this table. If the join requires values,
-   *   this clause should use a named placeholder and the value or values to
-   *   insert should be passed in the 4th parameter. For the first table joined
-   *   on a query, this value is ignored as the first table is taken as the base
-   *   table. The token %alias can be used in this string to be replaced with
-   *   the actual alias. This is useful when $alias is modified by the database
-   *   system, for example, when joining the same table more than once.
-   * @param $arguments
-   *   An array of arguments to replace into the $condition of this join.
-   * @return
-   *   The unique alias that was assigned for this table.
-   */
-  public function join($table, $alias = NULL, $condition = NULL, $arguments = array());
-
-  /**
-   * Inner Join against another table in the database.
-   *
-   * @param $table
-   *   The table against which to join.
-   * @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.
-   * @param $condition
-   *   The condition on which to join this table. If the join requires values,
-   *   this clause should use a named placeholder and the value or values to
-   *   insert should be passed in the 4th parameter. For the first table joined
-   *   on a query, this value is ignored as the first table is taken as the base
-   *   table. The token %alias can be used in this string to be replaced with
-   *   the actual alias. This is useful when $alias is modified by the database
-   *   system, for example, when joining the same table more than once.
-   * @param $arguments
-   *   An array of arguments to replace into the $condition of this join.
-   * @return
-   *   The unique alias that was assigned for this table.
-   */
-  public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = array());
-
-  /**
-   * Left Outer Join against another table in the database.
-   *
-   * @param $table
-   *   The table against which to join.
-   * @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.
-   * @param $condition
-   *   The condition on which to join this table. If the join requires values,
-   *   this clause should use a named placeholder and the value or values to
-   *   insert should be passed in the 4th parameter. For the first table joined
-   *   on a query, this value is ignored as the first table is taken as the base
-   *   table. The token %alias can be used in this string to be replaced with
-   *   the actual alias. This is useful when $alias is modified by the database
-   *   system, for example, when joining the same table more than once.
-   * @param $arguments
-   *   An array of arguments to replace into the $condition of this join.
-   * @return
-   *   The unique alias that was assigned for this table.
-   */
-  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array());
-
-  /**
-   * Right Outer Join against another table in the database.
-   *
-   * @param $table
-   *   The table against which to join.
-   * @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.
-   * @param $condition
-   *   The condition on which to join this table. If the join requires values,
-   *   this clause should use a named placeholder and the value or values to
-   *   insert should be passed in the 4th parameter. For the first table joined
-   *   on a query, this value is ignored as the first table is taken as the base
-   *   table. The token %alias can be used in this string to be replaced with
-   *   the actual alias. This is useful when $alias is modified by the database
-   *   system, for example, when joining the same table more than once.
-   * @param $arguments
-   *   An array of arguments to replace into the $condition of this join.
-   * @return
-   *   The unique alias that was assigned for this table.
-   */
-  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array());
-
-  /**
-   * Join against another table in the database.
-   *
-   * This method does the "hard" work of queuing up a table to be joined against.
-   * 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. 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,
-   *   one will be dynamically generated.
-   * @param $condition
-   *   The condition on which to join this table. If the join requires values,
-   *   this clause should use a named placeholder and the value or values to
-   *   insert should be passed in the 4th parameter. For the first table joined
-   *   on a query, this value is ignored as the first table is taken as the base
-   *   table. The token %alias can be used in this string to be replaced with
-   *   the actual alias. This is useful when $alias is modified by the database
-   *   system, for example, when joining the same table more than once.
-   * @param $arguments
-   *   An array of arguments to replace into the $condition of this join.
-   * @return
-   *   The unique alias that was assigned for this table.
-   */
-  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array());
-
-  /**
-   * Orders the result set by a given field.
-   *
-   * If called multiple times, the query will order by each specified field in the
-   * order this method is called.
-   *
-   * If the query uses DISTINCT or GROUP BY conditions, fields or expressions
-   * that are used for the order must be selected to be compatible with some
-   * databases like PostgreSQL. The PostgreSQL driver can handle simple cases
-   * automatically but it is suggested to explicitly specify them. Additionally,
-   * when ordering on an alias, the alias must be added before orderBy() is
-   * called.
-   *
-   * @param $field
-   *   The field on which to order.
-   * @param $direction
-   *   The direction to sort. Legal values are "ASC" and "DESC".
-   * @return SelectQueryInterface
-   *   The called object.
-   */
-  public function orderBy($field, $direction = 'ASC');
-
-  /**
-   * Orders the result set by a random value.
-   *
-   * This may be stacked with other orderBy() calls. If so, the query will order
-   * by each specified field, including this one, in the order called. Although
-   * this method may be called multiple times on the same query, doing so
-   * is not particularly useful.
-   *
-   * Note: The method used by most drivers may not scale to very large result
-   * sets. If you need to work with extremely large data sets, you may create
-   * your own database driver by subclassing off of an existing driver and
-   * implementing your own randomization mechanism. See
-   *
-   * http://jan.kneschke.de/projects/mysql/order-by-rand/
-   *
-   * for an example of such an alternate sorting mechanism.
-   *
-   * @return SelectQueryInterface
-   *   The called object
-   */
-  public function orderRandom();
-
-  /**
-   * Restricts a query to a given range in the result set.
-   *
-   * If this method is called with no parameters, will remove any range
-   * directives that have been set.
-   *
-   * @param $start
-   *   The first record from the result set to return. If NULL, removes any
-   *   range directives that are set.
-   * @param $length
-   *   The number of records to return from the result set.
-   * @return SelectQueryInterface
-   *   The called object.
-   */
-  public function range($start = NULL, $length = NULL);
-
-  /**
-   * Add another Select query to UNION to this one.
-   *
-   * Union queries consist of two or more queries whose
-   * results are effectively concatenated together. Queries
-   * will be UNIONed in the order they are specified, with
-   * this object's query coming first. Duplicate columns will
-   * be discarded. All forms of UNION are supported, using
-   * the second '$type' argument.
-   *
-   * Note: All queries UNIONed together must have the same
-   * field structure, in the same order. It is up to the
-   * caller to ensure that they match properly. If they do
-   * not, an SQL syntax error will result.
-   *
-   * @param $query
-   *   The query to UNION to this query.
-   * @param $type
-   *   The type of UNION to add to the query. Defaults to plain
-   *   UNION.
-   * @return SelectQueryInterface
-   *   The called object.
-   */
-  public function union(SelectQueryInterface $query, $type = '');
-
-  /**
-   * Groups the result set by the specified field.
-   *
-   * @param $field
-   *   The field on which to group. This should be the field as aliased.
-   * @return SelectQueryInterface
-   *   The called object.
-   */
-  public function groupBy($field);
-
-  /**
-   * Get the equivalent COUNT query of this query as a new query object.
-   *
-   * @return SelectQueryInterface
-   *   A new SelectQuery object with no fields or expressions besides COUNT(*).
-   */
-  public function countQuery();
-
-  /**
-   * Indicates if preExecute() has already been called on that object.
-   *
-   * @return
-   *   TRUE is this query has already been prepared, FALSE otherwise.
-   */
-  public function isPrepared();
-
-  /**
-   * Generic preparation and validation for a SELECT query.
-   *
-   * @return
-   *   TRUE if the validation was successful, FALSE if not.
-   */
-  public function preExecute(SelectQueryInterface $query = NULL);
-
-  /**
-   * Helper function to build most common HAVING conditional clauses.
-   *
-   * This method can take a variable number of parameters. If called with two
-   * parameters, they are taken as $field and $value with $operator having a value
-   * of IN if $value is an array and = otherwise.
-   *
-   * @param $field
-   *   The name of the field to check. If you would like to add a more complex
-   *   condition involving operators or functions, use having().
-   * @param $value
-   *   The value to test the field against. In most cases, this is a scalar. For more
-   *   complex options, it is an array. The meaning of each element in the array is
-   *   dependent on the $operator.
-   * @param $operator
-   *   The comparison operator, such as =, <, or >=. It also accepts more complex
-   *   options such as IN, LIKE, or BETWEEN. Defaults to IN if $value is an array
-   *   = otherwise.
-   * @return QueryConditionInterface
-   *   The called object.
-   */
-  public function havingCondition($field, $value = NULL, $operator = NULL);
-
-  /**
-   * Clone magic method.
-   *
-   * Select queries have dependent objects that must be deep-cloned.  The
-   * connection object itself, however, should not be cloned as that would
-   * duplicate the connection itself.
-   */
-  public function __clone();
-
-  /**
-   * Add FOR UPDATE to the query.
-   *
-   * FOR UPDATE prevents the rows retrieved by the SELECT statement from being
-   * modified or deleted by other transactions until the current transaction
-   * ends. Other transactions that attempt UPDATE, DELETE, or SELECT FOR UPDATE
-   * of these rows will be blocked until the current transaction ends.
-   *
-   * @param $set
-   *   IF TRUE, FOR UPDATE will be added to the query, if FALSE then it won't.
-   *
-   * @return QueryConditionInterface
-   *   The called object.
-   */
-  public function forUpdate($set = TRUE);
-}
-
-/**
- * The base extender class for Select queries.
- */
-class SelectQueryExtender implements SelectQueryInterface {
-
-  /**
-   * The SelectQuery object we are extending/decorating.
-   *
-   * @var SelectQueryInterface
-   */
-  protected $query;
-
-  /**
-   * The connection object on which to run this query.
-   *
-   * @var DatabaseConnection
-   */
-  protected $connection;
-
-  /**
-   * A unique identifier for this query object.
-   */
-  protected $uniqueIdentifier;
-
-  /**
-   * The placeholder counter.
-   */
-  protected $placeholder = 0;
-
-  public function __construct(SelectQueryInterface $query, DatabaseConnection $connection) {
-    $this->uniqueIdentifier = uniqid('', TRUE);
-    $this->query = $query;
-    $this->connection = $connection;
-  }
-
-  /**
-   * Implements QueryPlaceholderInterface::uniqueIdentifier().
-   */
-  public function uniqueIdentifier() {
-    return $this->uniqueIdentifier;
-  }
-
-  /**
-   * Implements QueryPlaceholderInterface::nextPlaceholder().
-   */
-  public function nextPlaceholder() {
-    return $this->placeholder++;
-  }
-
-  /* Implementations of QueryAlterableInterface. */
-
-  public function addTag($tag) {
-    $this->query->addTag($tag);
-    return $this;
-  }
-
-  public function hasTag($tag) {
-    return $this->query->hasTag($tag);
-  }
-
-  public function hasAllTags() {
-    return call_user_func_array(array($this->query, 'hasAllTags'), func_get_args());
-  }
-
-  public function hasAnyTag() {
-    return call_user_func_array(array($this->query, 'hasAnyTags'), func_get_args());
-  }
-
-  public function addMetaData($key, $object) {
-    $this->query->addMetaData($key, $object);
-    return $this;
-  }
-
-  public function getMetaData($key) {
-    return $this->query->getMetaData($key);
-  }
-
-  /* Implementations of QueryConditionInterface for the WHERE clause. */
-
-  public function condition($field, $value = NULL, $operator = NULL) {
-    $this->query->condition($field, $value, $operator);
-    return $this;
-  }
-
-  public function &conditions() {
-    return $this->query->conditions();
-  }
-
-  public function arguments() {
-    return $this->query->arguments();
-  }
-
-  public function where($snippet, $args = array()) {
-    $this->query->where($snippet, $args);
-    return $this;
-  }
-
-  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
-    return $this->query->compile($connection, $queryPlaceholder);
-  }
-
-  public function compiled() {
-    return $this->query->compiled();
-  }
-
-  /* Implementations of QueryConditionInterface for the HAVING clause. */
-
-  public function havingCondition($field, $value = NULL, $operator = '=') {
-    $this->query->havingCondition($field, $value, $operator);
-    return $this;
-  }
-
-  public function &havingConditions() {
-    return $this->query->havingConditions();
-  }
-
-  public function havingArguments() {
-    return $this->query->havingArguments();
-  }
-
-  public function having($snippet, $args = array()) {
-    $this->query->having($snippet, $args);
-    return $this;
-  }
-
-  public function havingCompile(DatabaseConnection $connection) {
-    return $this->query->havingCompile($connection);
-  }
-
-  /* Implementations of QueryExtendableInterface. */
-
-  public function extend($extender_name) {
-    // The extender can be anywhere so this needs to go to the registry, which
-    // is surely loaded by now.
-    $class = $this->connection->getDriverClass($extender_name, array(), TRUE);
-    return new $class($this, $this->connection);
-  }
-
-  /* Alter accessors to expose the query data to alter hooks. */
-
-  public function &getFields() {
-    return $this->query->getFields();
-  }
-
-  public function &getExpressions() {
-    return $this->query->getExpressions();
-  }
-
-  public function &getOrderBy() {
-    return $this->query->getOrderBy();
-  }
-
-  public function &getGroupBy() {
-    return $this->query->getGroupBy();
-  }
-
-  public function &getTables() {
-    return $this->query->getTables();
-  }
-
-  public function &getUnion() {
-    return $this->query->getUnion();
-  }
-
-  public function getArguments(QueryPlaceholderInterface $queryPlaceholder = NULL) {
-    return $this->query->getArguments($queryPlaceholder);
-  }
-
-  public function isPrepared() {
-    return $this->query->isPrepared();
-  }
-
-  public function preExecute(SelectQueryInterface $query = NULL) {
-    // If no query object is passed in, use $this.
-    if (!isset($query)) {
-      $query = $this;
-    }
-
-    return $this->query->preExecute($query);
-  }
-
-  public function execute() {
-    // By calling preExecute() here, we force it to preprocess the extender
-    // object rather than just the base query object.  That means
-    // hook_query_alter() gets access to the extended object.
-    if (!$this->preExecute($this)) {
-      return NULL;
-    }
-
-    return $this->query->execute();
-  }
-
-  public function distinct($distinct = TRUE) {
-    $this->query->distinct($distinct);
-    return $this;
-  }
-
-  public function addField($table_alias, $field, $alias = NULL) {
-    return $this->query->addField($table_alias, $field, $alias);
-  }
-
-  public function fields($table_alias, array $fields = array()) {
-    $this->query->fields($table_alias, $fields);
-    return $this;
-  }
-
-  public function addExpression($expression, $alias = NULL, $arguments = array()) {
-    return $this->query->addExpression($expression, $alias, $arguments);
-  }
-
-  public function join($table, $alias = NULL, $condition = NULL, $arguments = array()) {
-    return $this->query->join($table, $alias, $condition, $arguments);
-  }
-
-  public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
-    return $this->query->innerJoin($table, $alias, $condition, $arguments);
-  }
-
-  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
-    return $this->query->leftJoin($table, $alias, $condition, $arguments);
-  }
-
-  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
-    return $this->query->rightJoin($table, $alias, $condition, $arguments);
-  }
-
-  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array()) {
-    return $this->query->addJoin($type, $table, $alias, $condition, $arguments);
-  }
-
-  public function orderBy($field, $direction = 'ASC') {
-    $this->query->orderBy($field, $direction);
-    return $this;
-  }
-
-  public function orderRandom() {
-    $this->query->orderRandom();
-    return $this;
-  }
-
-  public function range($start = NULL, $length = NULL) {
-    $this->query->range($start, $length);
-    return $this;
-  }
-
-  public function union(SelectQueryInterface $query, $type = '') {
-    $this->query->union($query, $type);
-    return $this;
-  }
-
-  public function groupBy($field) {
-    $this->query->groupBy($field);
-    return $this;
-  }
-
-  public function forUpdate($set = TRUE) {
-    $this->query->forUpdate($set);
-    return $this;
-  }
-
-  public function countQuery() {
-    return $this->query->countQuery();
-  }
-
-  function isNull($field) {
-    $this->query->isNull($field);
-    return $this;
-  }
-
-  function isNotNull($field) {
-    $this->query->isNotNull($field);
-    return $this;
-  }
-
-  public function exists(SelectQueryInterface $select) {
-    $this->query->exists($select);
-    return $this;
-  }
-
-  public function notExists(SelectQueryInterface $select) {
-    $this->query->notExists($select);
-    return $this;
-  }
-
-  public function __toString() {
-    return (string) $this->query;
-  }
-
-  public function __clone() {
-    $this->uniqueIdentifier = uniqid('', TRUE);
-
-    // We need to deep-clone the query we're wrapping, which in turn may
-    // deep-clone other objects.  Exciting!
-    $this->query = clone($this->query);
-  }
-
-  /**
-   * Magic override for undefined methods.
-   *
-   * If one extender extends another extender, then methods in the inner extender
-   * will not be exposed on the outer extender.  That's because we cannot know
-   * in advance what those methods will be, so we cannot provide wrapping
-   * implementations as we do above.  Instead, we use this slower catch-all method
-   * to handle any additional methods.
-   */
-  public function __call($method, $args) {
-    $return = call_user_func_array(array($this->query, $method), $args);
-
-    // Some methods will return the called object as part of a fluent interface.
-    // Others will return some useful value.  If it's a value, then the caller
-    // probably wants that value.  If it's the called object, then we instead
-    // return this object.  That way we don't "lose" an extender layer when
-    // chaining methods together.
-    if ($return instanceof SelectQueryInterface) {
-      return $this;
-    }
-    else {
-      return $return;
-    }
-  }
-}
-
-/**
- * Query builder for SELECT statements.
- */
-class SelectQuery extends Query implements SelectQueryInterface {
-
-  /**
-   * The fields to SELECT.
-   *
-   * @var array
-   */
-  protected $fields = array();
-
-  /**
-   * The expressions to SELECT as virtual fields.
-   *
-   * @var array
-   */
-  protected $expressions = array();
-
-  /**
-   * The tables against which to JOIN.
-   *
-   * This property is a nested array. Each entry is an array representing
-   * a single table against which to join. The structure of each entry is:
-   *
-   * array(
-   *   'type' => $join_type (one of INNER, LEFT OUTER, RIGHT OUTER),
-   *   'table' => $table,
-   *   'alias' => $alias_of_the_table,
-   *   'condition' => $condition_clause_on_which_to_join,
-   *   'arguments' => $array_of_arguments_for_placeholders_in_the condition.
-   *   'all_fields' => TRUE to SELECT $alias.*, FALSE or NULL otherwise.
-   * )
-   *
-   * If $table is a string, it is taken as the name of a table. If it is
-   * a SelectQuery object, it is taken as a subquery.
-   *
-   * @var array
-   */
-  protected $tables = array();
-
-  /**
-   * The fields by which to order this query.
-   *
-   * This is an associative array. The keys are the fields to order, and the value
-   * is the direction to order, either ASC or DESC.
-   *
-   * @var array
-   */
-  protected $order = array();
-
-  /**
-   * The fields by which to group.
-   *
-   * @var array
-   */
-  protected $group = array();
-
-  /**
-   * The conditional object for the WHERE clause.
-   *
-   * @var DatabaseCondition
-   */
-  protected $where;
-
-  /**
-   * The conditional object for the HAVING clause.
-   *
-   * @var DatabaseCondition
-   */
-  protected $having;
-
-  /**
-   * Whether or not this query should be DISTINCT
-   *
-   * @var boolean
-   */
-  protected $distinct = FALSE;
-
-  /**
-   * The range limiters for this query.
-   *
-   * @var array
-   */
-  protected $range;
-
-  /**
-   * An array whose elements specify a query to UNION, and the UNION type. The
-   * 'type' key may be '', 'ALL', or 'DISTINCT' to represent a 'UNION',
-   * 'UNION ALL', or 'UNION DISTINCT' statement, respectively.
-   *
-   * All entries in this array will be applied from front to back, with the
-   * first query to union on the right of the original query, the second union
-   * to the right of the first, etc.
-   *
-   * @var array
-   */
-  protected $union = array();
-
-  /**
-   * Indicates if preExecute() has already been called.
-   * @var boolean
-   */
-  protected $prepared = FALSE;
-
-  /**
-   * The FOR UPDATE status
-   */
-  protected $forUpdate = FALSE;
-
-  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->addJoin(NULL, $table, $alias);
-  }
-
-  /* Implementations of QueryAlterableInterface. */
-
-  public function addTag($tag) {
-    $this->alterTags[$tag] = 1;
-    return $this;
-  }
-
-  public function hasTag($tag) {
-    return isset($this->alterTags[$tag]);
-  }
-
-  public function hasAllTags() {
-    return !(boolean)array_diff(func_get_args(), array_keys($this->alterTags));
-  }
-
-  public function hasAnyTag() {
-    return (boolean)array_intersect(func_get_args(), array_keys($this->alterTags));
-  }
-
-  public function addMetaData($key, $object) {
-    $this->alterMetaData[$key] = $object;
-    return $this;
-  }
-
-  public function getMetaData($key) {
-    return isset($this->alterMetaData[$key]) ? $this->alterMetaData[$key] : NULL;
-  }
-
-  /* Implementations of QueryConditionInterface for the WHERE clause. */
-
-  public function condition($field, $value = NULL, $operator = NULL) {
-    $this->where->condition($field, $value, $operator);
-    return $this;
-  }
-
-  public function &conditions() {
-    return $this->where->conditions();
-  }
-
-  public function arguments() {
-    if (!$this->compiled()) {
-      return NULL;
-    }
-
-    $args = $this->where->arguments() + $this->having->arguments();
-
-    foreach ($this->tables as $table) {
-      if ($table['arguments']) {
-        $args += $table['arguments'];
-      }
-      // If this table is a subquery, grab its arguments recursively.
-      if ($table['table'] instanceof SelectQueryInterface) {
-        $args += $table['table']->arguments();
-      }
-    }
-
-    foreach ($this->expressions as $expression) {
-      if ($expression['arguments']) {
-        $args += $expression['arguments'];
-      }
-    }
-
-    // If there are any dependent queries to UNION,
-    // incorporate their arguments recursively.
-    foreach ($this->union as $union) {
-      $args += $union['query']->arguments();
-    }
-
-    return $args;
-  }
-
-  public function where($snippet, $args = array()) {
-    $this->where->where($snippet, $args);
-    return $this;
-  }
-
-  public function isNull($field) {
-    $this->where->isNull($field);
-    return $this;
-  }
-
-  public function isNotNull($field) {
-    $this->where->isNotNull($field);
-    return $this;
-  }
-
-  public function exists(SelectQueryInterface $select) {
-    $this->where->exists($select);
-    return $this;
-  }
-
-  public function notExists(SelectQueryInterface $select) {
-    $this->where->notExists($select);
-    return $this;
-  }
-
-  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
-    $this->where->compile($connection, $queryPlaceholder);
-    $this->having->compile($connection, $queryPlaceholder);
-
-    foreach ($this->tables as $table) {
-      // If this table is a subquery, compile it recursively.
-      if ($table['table'] instanceof SelectQueryInterface) {
-        $table['table']->compile($connection, $queryPlaceholder);
-      }
-    }
-
-    // If there are any dependent queries to UNION, compile it recursively.
-    foreach ($this->union as $union) {
-      $union['query']->compile($connection, $queryPlaceholder);
-    }
-  }
-
-  public function compiled() {
-    if (!$this->where->compiled() || !$this->having->compiled()) {
-      return FALSE;
-    }
-
-    foreach ($this->tables as $table) {
-      // If this table is a subquery, check its status recursively.
-      if ($table['table'] instanceof SelectQueryInterface) {
-        if (!$table['table']->compiled()) {
-          return FALSE;
-        }
-      }
-    }
-
-    foreach ($this->union as $union) {
-      if (!$union['query']->compiled()) {
-        return FALSE;
-      }
-    }
-
-    return TRUE;
-  }
-
-  /* Implementations of QueryConditionInterface for the HAVING clause. */
-
-  public function havingCondition($field, $value = NULL, $operator = NULL) {
-    $this->having->condition($field, $value, $operator);
-    return $this;
-  }
-
-  public function &havingConditions() {
-    return $this->having->conditions();
-  }
-
-  public function havingArguments() {
-    return $this->having->arguments();
-  }
-
-  public function having($snippet, $args = array()) {
-    $this->having->where($snippet, $args);
-    return $this;
-  }
-
-  public function havingCompile(DatabaseConnection $connection) {
-    return $this->having->compile($connection, $this);
-  }
-
-  /* Implementations of QueryExtendableInterface. */
-
-  public function extend($extender_name) {
-    $override_class = $extender_name . '_' . $this->connection->driver();
-    if (class_exists($override_class)) {
-      $extender_name = $override_class;
-    }
-    return new $extender_name($this, $this->connection);
-  }
-
-  public function havingIsNull($field) {
-    $this->having->isNull($field);
-    return $this;
-  }
-
-  public function havingIsNotNull($field) {
-    $this->having->isNotNull($field);
-    return $this;
-  }
-
-  public function havingExists(SelectQueryInterface $select) {
-    $this->having->exists($select);
-    return $this;
-  }
-
-  public function havingNotExists(SelectQueryInterface $select) {
-    $this->having->notExists($select);
-    return $this;
-  }
-
-  public function forUpdate($set = TRUE) {
-    if (isset($set)) {
-      $this->forUpdate = $set;
-    }
-    return $this;
-  }
-
-  /* Alter accessors to expose the query data to alter hooks. */
-
-  public function &getFields() {
-    return $this->fields;
-  }
-
-  public function &getExpressions() {
-    return $this->expressions;
-  }
-
-  public function &getOrderBy() {
-    return $this->order;
-  }
-
-  public function &getGroupBy() {
-    return $this->group;
-  }
-
-  public function &getTables() {
-    return $this->tables;
-  }
-
-  public function &getUnion() {
-    return $this->union;
-  }
-
-  public function getArguments(QueryPlaceholderInterface $queryPlaceholder = NULL) {
-    if (!isset($queryPlaceholder)) {
-      $queryPlaceholder = $this;
-    }
-    $this->compile($this->connection, $queryPlaceholder);
-    return $this->arguments();
-  }
-
-  /**
-   * Indicates if preExecute() has already been called on that object.
-   */
-  public function isPrepared() {
-    return $this->prepared;
-  }
-
-  /**
-   * Generic preparation and validation for a SELECT query.
-   *
-   * @return
-   *   TRUE if the validation was successful, FALSE if not.
-   */
-  public function preExecute(SelectQueryInterface $query = NULL) {
-    // If no query object is passed in, use $this.
-    if (!isset($query)) {
-      $query = $this;
-    }
-
-    // Only execute this once.
-    if ($query->isPrepared()) {
-      return TRUE;
-    }
-
-    // Modules may alter all queries or only those having a particular tag.
-    if (isset($this->alterTags)) {
-      $hooks = array('query');
-      foreach ($this->alterTags as $tag => $value) {
-        $hooks[] = 'query_' . $tag;
-      }
-      drupal_alter($hooks, $query);
-    }
-
-    $this->prepared = TRUE;
-
-    // Now also prepare any sub-queries.
-    foreach ($this->tables as $table) {
-      if ($table['table'] instanceof SelectQueryInterface) {
-        $table['table']->preExecute();
-      }
-    }
-
-    foreach ($this->union as $union) {
-      $union['query']->preExecute();
-    }
-
-    return $this->prepared;
-  }
-
-  public function execute() {
-    // If validation fails, simply return NULL.
-    // Note that validation routines in preExecute() may throw exceptions instead.
-    if (!$this->preExecute()) {
-      return NULL;
-    }
-
-    $args = $this->getArguments();
-    return $this->connection->query((string) $this, $args, $this->queryOptions);
-  }
-
-  public function distinct($distinct = TRUE) {
-    $this->distinct = $distinct;
-    return $this;
-  }
-
-  public function addField($table_alias, $field, $alias = NULL) {
-    // If no alias is specified, first try the field name itself.
-    if (empty($alias)) {
-      $alias = $field;
-    }
-
-    // If that's already in use, try the table name and field name.
-    if (!empty($this->fields[$alias])) {
-      $alias = $table_alias . '_' . $field;
-    }
-
-    // If that is already used, just add a counter until we find an unused alias.
-    $alias_candidate = $alias;
-    $count = 2;
-    while (!empty($this->fields[$alias_candidate])) {
-      $alias_candidate = $alias . '_' . $count++;
-    }
-    $alias = $alias_candidate;
-
-    $this->fields[$alias] = array(
-      'field' => $field,
-      'table' => $table_alias,
-      'alias' => $alias,
-    );
-
-    return $alias;
-  }
-
-  public function fields($table_alias, array $fields = array()) {
-
-    if ($fields) {
-      foreach ($fields as $field) {
-        // We don't care what alias was assigned.
-        $this->addField($table_alias, $field);
-      }
-    }
-    else {
-      // We want all fields from this table.
-      $this->tables[$table_alias]['all_fields'] = TRUE;
-    }
-
-    return $this;
-  }
-
-  public function addExpression($expression, $alias = NULL, $arguments = array()) {
-    if (empty($alias)) {
-      $alias = 'expression';
-    }
-
-    $alias_candidate = $alias;
-    $count = 2;
-    while (!empty($this->expressions[$alias_candidate])) {
-      $alias_candidate = $alias . '_' . $count++;
-    }
-    $alias = $alias_candidate;
-
-    $this->expressions[$alias] = array(
-      'expression' => $expression,
-      'alias' => $alias,
-      'arguments' => $arguments,
-    );
-
-    return $alias;
-  }
-
-  public function join($table, $alias = NULL, $condition = NULL, $arguments = array()) {
-    return $this->addJoin('INNER', $table, $alias, $condition, $arguments);
-  }
-
-  public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
-    return $this->addJoin('INNER', $table, $alias, $condition, $arguments);
-  }
-
-  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
-    return $this->addJoin('LEFT OUTER', $table, $alias, $condition, $arguments);
-  }
-
-  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
-    return $this->addJoin('RIGHT OUTER', $table, $alias, $condition, $arguments);
-  }
-
-  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array()) {
-
-    if (empty($alias)) {
-      if ($table instanceof SelectQueryInterface) {
-        $alias = 'subquery';
-      }
-      else {
-        $alias = $table;
-      }
-    }
-
-    $alias_candidate = $alias;
-    $count = 2;
-    while (!empty($this->tables[$alias_candidate])) {
-      $alias_candidate = $alias . '_' . $count++;
-    }
-    $alias = $alias_candidate;
-
-    if (is_string($condition)) {
-      $condition = str_replace('%alias', $alias, $condition);
-    }
-
-    $this->tables[$alias] = array(
-      'join type' => $type,
-      'table' => $table,
-      'alias' => $alias,
-      'condition' => $condition,
-      'arguments' => $arguments,
-    );
-
-    return $alias;
-  }
-
-  public function orderBy($field, $direction = 'ASC') {
-    $this->order[$field] = $direction;
-    return $this;
-  }
-
-  public function orderRandom() {
-    $alias = $this->addExpression('RAND()', 'random_field');
-    $this->orderBy($alias);
-    return $this;
-  }
-
-  public function range($start = NULL, $length = NULL) {
-    $this->range = func_num_args() ? array('start' => $start, 'length' => $length) : array();
-    return $this;
-  }
-
-  public function union(SelectQueryInterface $query, $type = '') {
-    // Handle UNION aliasing.
-    switch ($type) {
-      // Fold UNION DISTINCT to UNION for better cross database support.
-      case 'DISTINCT':
-      case '':
-        $type = 'UNION';
-        break;
-
-      case 'ALL':
-        $type = 'UNION ALL';
-      default:
-    }
-
-    $this->union[] = array(
-      'type' => $type,
-      'query' => $query,
-    );
-
-    return $this;
-  }
-
-  public function groupBy($field) {
-    $this->group[$field] = $field;
-    return $this;
-  }
-
-  public function countQuery() {
-    // Create our new query object that we will mutate into a count query.
-    $count = clone($this);
-
-    $group_by = $count->getGroupBy();
-    $having = $count->havingConditions();
-
-    if (!$count->distinct && !isset($having[0])) {
-      // When not executing a distinct query, we can zero-out existing fields
-      // and expressions that are not used by a GROUP BY or HAVING. Fields
-      // listed in a GROUP BY or HAVING clause need to be present in the
-      // query.
-      $fields =& $count->getFields();
-      foreach (array_keys($fields) as $field) {
-        if (empty($group_by[$field])) {
-          unset($fields[$field]);
-        }
-      }
-
-      $expressions =& $count->getExpressions();
-      foreach (array_keys($expressions) as $field) {
-        if (empty($group_by[$field])) {
-          unset($expressions[$field]);
-        }
-      }
-
-      // Also remove 'all_fields' statements, which are expanded into tablename.*
-      // when the query is executed.
-      foreach ($count->tables as $alias => &$table) {
-        unset($table['all_fields']);
-      }
-    }
-
-    // If we've just removed all fields from the query, make sure there is at
-    // least one so that the query still runs.
-    $count->addExpression('1');
-
-    // Ordering a count query is a waste of cycles, and breaks on some
-    // databases anyway.
-    $orders = &$count->getOrderBy();
-    $orders = array();
-
-    if ($count->distinct && !empty($group_by)) {
-      // If the query is distinct and contains a GROUP BY, we need to remove the
-      // distinct because SQL99 does not support counting on distinct multiple fields.
-      $count->distinct = FALSE;
-    }
-
-    $query = $this->connection->select($count);
-    $query->addExpression('COUNT(*)');
-
-    return $query;
-  }
-
-  public function __toString() {
-    // For convenience, we compile the query ourselves if the caller forgot
-    // to do it. This allows constructs like "(string) $query" to work. When
-    // the query will be executed, it will be recompiled using the proper
-    // placeholder generator anyway.
-    if (!$this->compiled()) {
-      $this->compile($this->connection, $this);
-    }
-
-    // Create a sanitized comment string to prepend to the query.
-    $comments = $this->connection->makeComment($this->comments);
-
-    // SELECT
-    $query = $comments . 'SELECT ';
-    if ($this->distinct) {
-      $query .= 'DISTINCT ';
-    }
-
-    // FIELDS and EXPRESSIONS
-    $fields = array();
-    foreach ($this->tables as $alias => $table) {
-      if (!empty($table['all_fields'])) {
-        $fields[] = $this->connection->escapeTable($alias) . '.*';
-      }
-    }
-    foreach ($this->fields as $alias => $field) {
-      // Always use the AS keyword for field aliases, as some
-      // databases require it (e.g., PostgreSQL).
-      $fields[] = (isset($field['table']) ? $this->connection->escapeTable($field['table']) . '.' : '') . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']);
-    }
-    foreach ($this->expressions as $alias => $expression) {
-      $fields[] = $expression['expression'] . ' AS ' . $this->connection->escapeAlias($expression['alias']);
-    }
-    $query .= implode(', ', $fields);
-
-
-    // FROM - We presume all queries have a FROM, as any query that doesn't won't need the query builder anyway.
-    $query .= "\nFROM ";
-    foreach ($this->tables as $alias => $table) {
-      $query .= "\n";
-      if (isset($table['join type'])) {
-        $query .= $table['join type'] . ' JOIN ';
-      }
-
-      // If the table is a subquery, compile it and integrate it into this query.
-      if ($table['table'] instanceof SelectQueryInterface) {
-        // Run preparation steps on this sub-query before converting to string.
-        $subquery = $table['table'];
-        $subquery->preExecute();
-        $table_string = '(' . (string) $subquery . ')';
-      }
-      else {
-        $table_string = '{' . $this->connection->escapeTable($table['table']) . '}';
-      }
-
-      // Don't use the AS keyword for table aliases, as some
-      // databases don't support it (e.g., Oracle).
-      $query .=  $table_string . ' ' . $this->connection->escapeTable($table['alias']);
-
-      if (!empty($table['condition'])) {
-        $query .= ' ON ' . $table['condition'];
-      }
-    }
-
-    // WHERE
-    if (count($this->where)) {
-      // There is an implicit string cast on $this->condition.
-      $query .= "\nWHERE " . $this->where;
-    }
-
-    // GROUP BY
-    if ($this->group) {
-      $query .= "\nGROUP BY " . implode(', ', $this->group);
-    }
-
-    // HAVING
-    if (count($this->having)) {
-      // There is an implicit string cast on $this->having.
-      $query .= "\nHAVING " . $this->having;
-    }
-
-    // ORDER BY
-    if ($this->order) {
-      $query .= "\nORDER BY ";
-      $fields = array();
-      foreach ($this->order as $field => $direction) {
-        $fields[] = $field . ' ' . $direction;
-      }
-      $query .= implode(', ', $fields);
-    }
-
-    // RANGE
-    // There is no universal SQL standard for handling range or limit clauses.
-    // Fortunately, all core-supported databases use the same range syntax.
-    // Databases that need a different syntax can override this method and
-    // do whatever alternate logic they need to.
-    if (!empty($this->range)) {
-      $query .= "\nLIMIT " . (int) $this->range['length'] . " OFFSET " . (int) $this->range['start'];
-    }
-
-    // UNION is a little odd, as the select queries to combine are passed into
-    // this query, but syntactically they all end up on the same level.
-    if ($this->union) {
-      foreach ($this->union as $union) {
-        $query .= ' ' . $union['type'] . ' ' . (string) $union['query'];
-      }
-    }
-
-    if ($this->forUpdate) {
-      $query .= ' FOR UPDATE';
-    }
-
-    return $query;
-  }
-
-  public function __clone() {
-    // On cloning, also clone the dependent objects. However, we do not
-    // want to clone the database connection object as that would duplicate the
-    // connection itself.
-
-    $this->where = clone($this->where);
-    $this->having = clone($this->having);
-    foreach ($this->union as $key => $aggregate) {
-      $this->union[$key]['query'] = clone($aggregate['query']);
-    }
-  }
-}
-
-/**
- * @} End of "ingroup database".
- */
diff --git a/core/includes/database/sqlite/query.inc b/core/includes/database/sqlite/query.inc
deleted file mode 100644
index 6b8a72f2ab46aed8da9f908a7f66f4f71d27b11a..0000000000000000000000000000000000000000
--- a/core/includes/database/sqlite/query.inc
+++ /dev/null
@@ -1,160 +0,0 @@
-<?php
-
-/**
- * @file
- * Query code for SQLite embedded database engine.
- */
-
-/**
- * @ingroup database
- * @{
- */
-
-/**
- * SQLite specific implementation of InsertQuery.
- *
- * We ignore all the default fields and use the clever SQLite syntax:
- *   INSERT INTO table DEFAULT VALUES
- * for degenerated "default only" queries.
- */
-class InsertQuery_sqlite extends InsertQuery {
-
-  public function execute() {
-    if (!$this->preExecute()) {
-      return NULL;
-    }
-    if (count($this->insertFields)) {
-      return parent::execute();
-    }
-    else {
-      return $this->connection->query('INSERT INTO {' . $this->table . '} DEFAULT VALUES', array(), $this->queryOptions);
-    }
-  }
-
-  public function __toString() {
-    // Create a sanitized comment string to prepend to the query.
-    $comments = $this->connection->makeComment($this->comments);
-
-    // Produce as many generic placeholders as necessary.
-    $placeholders = array_fill(0, count($this->insertFields), '?');
-
-    // If we're selecting from a SelectQuery, finish building the query and
-    // pass it back, as any remaining options are irrelevant.
-    if (!empty($this->fromQuery)) {
-      return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') ' . $this->fromQuery;
-    }
-
-    return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') VALUES (' . implode(', ', $placeholders) . ')';
-  }
-
-}
-
-/**
- * SQLite specific implementation of UpdateQuery.
- *
- * SQLite counts all the rows that match the conditions as modified, even if they
- * will not be affected by the query. We workaround this by ensuring that
- * we don't select those rows.
- *
- * A query like this one:
- *   UPDATE test SET name = 'newname' WHERE tid = 1
- * will become:
- *   UPDATE test SET name = 'newname' WHERE tid = 1 AND name <> 'newname'
- */
-class UpdateQuery_sqlite extends UpdateQuery {
-  /**
-   * Helper function that removes the fields that are already in a condition.
-   *
-   * @param $fields
-   *   The fields.
-   * @param QueryConditionInterface $condition
-   *   A database condition.
-   */
-  protected function removeFieldsInCondition(&$fields, QueryConditionInterface $condition) {
-    foreach ($condition->conditions() as $child_condition) {
-      if ($child_condition['field'] instanceof QueryConditionInterface) {
-        $this->removeFieldsInCondition($fields, $child_condition['field']);
-      }
-      else {
-        unset($fields[$child_condition['field']]);
-      }
-    }
-  }
-
-  public function execute() {
-    if (!empty($this->queryOptions['sqlite_return_matched_rows'])) {
-      return parent::execute();
-    }
-
-    // Get the fields used in the update query, and remove those that are already
-    // in the condition.
-    $fields = $this->expressionFields + $this->fields;
-    $this->removeFieldsInCondition($fields, $this->condition);
-
-    // Add the inverse of the fields to the condition.
-    $condition = new DatabaseCondition('OR');
-    foreach ($fields as $field => $data) {
-      if (is_array($data)) {
-        // The field is an expression.
-        $condition->where($field . ' <> ' . $data['expression']);
-        $condition->isNull($field);
-      }
-      elseif (!isset($data)) {
-        // The field will be set to NULL.
-        $condition->isNotNull($field);
-      }
-      else {
-        $condition->condition($field, $data, '<>');
-        $condition->isNull($field);
-      }
-    }
-    if (count($condition)) {
-      $condition->compile($this->connection, $this);
-      $this->condition->where((string) $condition, $condition->arguments());
-    }
-    return parent::execute();
-  }
-
-}
-
-/**
- * SQLite specific implementation of DeleteQuery.
- *
- * When the WHERE is omitted from a DELETE statement and the table being deleted
- * has no triggers, SQLite uses an optimization to erase the entire table content
- * without having to visit each row of the table individually.
- *
- * Prior to SQLite 3.6.5, SQLite does not return the actual number of rows deleted
- * by that optimized "truncate" optimization.
- */
-class DeleteQuery_sqlite extends DeleteQuery {
-  public function execute() {
-    if (!count($this->condition)) {
-      $total_rows = $this->connection->query('SELECT COUNT(*) FROM {' . $this->connection->escapeTable($this->table) . '}')->fetchField();
-      parent::execute();
-      return $total_rows;
-    }
-    else {
-      return parent::execute();
-    }
-  }
-}
-
-/**
- * SQLite specific implementation of TruncateQuery.
- *
- * SQLite doesn't support TRUNCATE, but a DELETE query with no condition has
- * exactly the effect (it is implemented by DROPing the table).
- */
-class TruncateQuery_sqlite extends TruncateQuery {
-  public function __toString() {
-    // Create a sanitized comment string to prepend to the query.
-    $comments = $this->connection->makeComment($this->comments);
-
-    return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '} ';
-  }
-}
-
-/**
- * @} End of "ingroup database".
- */
diff --git a/core/includes/database/sqlite/select.inc b/core/includes/database/sqlite/select.inc
deleted file mode 100644
index fb926ef04d3124d7cb8efe35a7e51a0e81301f6c..0000000000000000000000000000000000000000
--- a/core/includes/database/sqlite/select.inc
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-/**
- * @file
- * Select builder for SQLite embedded database engine.
- */
-
-/**
- * @ingroup database
- * @{
- */
-
-/**
- * SQLite specific query builder for SELECT statements.
- */
-class SelectQuery_sqlite extends SelectQuery {
-  public function forUpdate($set = TRUE) {
-    // SQLite does not support FOR UPDATE so nothing to do.
-    return $this;
-  }
-}
-
-/**
- * @} End of "ingroup database".
- */
-
-
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index d4514883e6c670c7ca145cc64b3b5e72b35d995e..1936b833470bcde696e8401ec70cf2baccdc6a3f 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1,5 +1,8 @@
 <?php
 
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Install\TaskException;
+
 /**
  * @file
  * API functions for installing Drupal.
@@ -223,6 +226,27 @@ function install_begin_request(&$install_state) {
 
   // Allow command line scripts to override server variables used by Drupal.
   require_once DRUPAL_ROOT . '/core/includes/bootstrap.inc';
+
+  // Ensure that the class loader is available so that we can leverage classes
+  // as part of the install routine.
+  $loader = drupal_classloader();
+
+  // Register explicit vendor namespaces.
+  $loader->registerNamespaces(array(
+    // All Symfony-borrowed code lives in /core/includes/Symfony.
+    'Symfony' => DRUPAL_ROOT . '/core/vendor',
+  ));
+  // Register the Drupal namespace for classes in core as a fallback.
+  // This allows to register additional namespaces within the Drupal namespace
+  // (e.g., for modules) and avoids an additional file_exists() on the Drupal
+  // core namespace, since the class loader can already determine the best
+  // namespace match based on a string comparison. It further allows modules to
+  // register/overload namespaces in Drupal core.
+  $loader->registerNamespaceFallbacks(array(
+    // All Drupal-namespaced code in core lives in /core/includes/Drupal.
+    'Drupal' => DRUPAL_ROOT . '/core/lib',
+  ));
+
   if (!$install_state['interactive']) {
     drupal_override_server_variables($install_state['server']);
   }
@@ -961,7 +985,7 @@ function install_database_errors($database, $settings_file) {
     try {
       db_run_tasks($driver);
     }
-    catch (DatabaseTaskException $e) {
+    catch (TaskException $e) {
       // These are generic errors, so we do not have any specific key of the
       // database connection array to attach them to; therefore, we just put
       // them in the error array with standard numeric keys.
diff --git a/core/includes/install.inc b/core/includes/install.inc
index a7b4dc7ec4a4212a63138140b32352189482a983..fb10d7b098871a465d92b09b0a04af515d0b71fb 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * Indicates that a module has not been installed yet.
  */
@@ -246,6 +248,7 @@ function drupal_detect_database_types() {
  */
 function drupal_get_database_types() {
   $databases = array();
+  $drivers = array();
 
   // We define a driver as a directory in /core/includes/database that in turn
   // contains a database.inc file. That allows us to drop in additional drivers
@@ -253,8 +256,8 @@ function drupal_get_database_types() {
   // Because we have no registry yet, we need to also include the install.inc
   // file for the driver explicitly.
   require_once DRUPAL_ROOT . '/core/includes/database/database.inc';
-  foreach (file_scan_directory(DRUPAL_ROOT . '/core/includes/database', '/^[a-z]*$/i', array('recurse' => FALSE)) as $file) {
-    if (file_exists($file->uri . '/database.inc') && file_exists($file->uri . '/install.inc')) {
+  foreach (file_scan_directory(DRUPAL_ROOT . '/core/lib/Drupal/Core/Database/Driver', '/^[a-z]*$/i', array('recurse' => FALSE)) as $file) {
+    if (file_exists($file->uri . '/Install/Tasks.php')) {
       $drivers[$file->filename] = $file->uri;
     }
   }
@@ -276,305 +279,6 @@ function drupal_get_database_types() {
   return $databases;
 }
 
-/**
- * Database installer structure.
- *
- * Defines basic Drupal requirements for databases.
- */
-abstract class DatabaseTasks {
-
-  /**
-   * Structure that describes each task to run.
-   *
-   * @var array
-   *
-   * Each value of the tasks array is an associative array defining the function
-   * to call (optional) and any arguments to be passed to the function.
-   */
-  protected $tasks = array(
-    array(
-      'function'    => 'checkEngineVersion',
-      'arguments'   => array(),
-    ),
-    array(
-      'arguments'   => array(
-        'CREATE TABLE {drupal_install_test} (id int NULL)',
-        'Drupal can use CREATE TABLE database commands.',
-        'Failed to <strong>CREATE</strong> a test table on your database server with the command %query. The server reports the following message: %error.<p>Are you sure the configured username has the necessary permissions to create tables in the database?</p>',
-        TRUE,
-      ),
-    ),
-    array(
-      'arguments'   => array(
-        'INSERT INTO {drupal_install_test} (id) VALUES (1)',
-        'Drupal can use INSERT database commands.',
-        'Failed to <strong>INSERT</strong> a value into a test table on your database server. We tried inserting a value with the command %query and the server reported the following error: %error.',
-      ),
-    ),
-    array(
-      'arguments'   => array(
-        'UPDATE {drupal_install_test} SET id = 2',
-        'Drupal can use UPDATE database commands.',
-        'Failed to <strong>UPDATE</strong> a value in a test table on your database server. We tried updating a value with the command %query and the server reported the following error: %error.',
-      ),
-    ),
-    array(
-      'arguments'   => array(
-        'DELETE FROM {drupal_install_test}',
-        'Drupal can use DELETE database commands.',
-        'Failed to <strong>DELETE</strong> a value from a test table on your database server. We tried deleting a value with the command %query and the server reported the following error: %error.',
-      ),
-    ),
-    array(
-      'arguments'   => array(
-        'DROP TABLE {drupal_install_test}',
-        'Drupal can use DROP TABLE database commands.',
-        'Failed to <strong>DROP</strong> a test table from your database server. We tried dropping a table with the command %query and the server reported the following error %error.',
-      ),
-    ),
-  );
-
-  /**
-   * Results from tasks.
-   *
-   * @var array
-   */
-  protected $results = array();
-
-  /**
-   * Ensure the PDO driver is supported by the version of PHP in use.
-   */
-  protected function hasPdoDriver() {
-    return in_array($this->pdoDriver, PDO::getAvailableDrivers());
-  }
-
-  /**
-   * Assert test as failed.
-   */
-  protected function fail($message) {
-    $this->results[$message] = FALSE;
-  }
-
-  /**
-   * Assert test as a pass.
-   */
-  protected function pass($message) {
-    $this->results[$message] = TRUE;
-  }
-
-  /**
-   * Check whether Drupal is installable on the database.
-   */
-  public function installable() {
-    return $this->hasPdoDriver() && empty($this->error);
-  }
-
-  /**
-   * Return the human-readable name of the driver.
-   */
-  abstract public function name();
-
-  /**
-   * Return the minimum required version of the engine.
-   *
-   * @return
-   *   A version string. If not NULL, it will be checked against the version
-   *   reported by the Database engine using version_compare().
-   */
-  public function minimumVersion() {
-    return NULL;
-  }
-
-  /**
-   * Run database tasks and tests to see if Drupal can run on the database.
-   */
-  public function runTasks() {
-    // We need to establish a connection before we can run tests.
-    if ($this->connect()) {
-      foreach ($this->tasks as $task) {
-        if (!isset($task['function'])) {
-          $task['function'] = 'runTestQuery';
-        }
-        if (method_exists($this, $task['function'])) {
-          // Returning false is fatal. No other tasks can run.
-          if (FALSE === call_user_func_array(array($this, $task['function']), $task['arguments'])) {
-            break;
-          }
-        }
-        else {
-          throw new DatabaseTaskException(st("Failed to run all tasks against the database server. The task %task wasn't found.", array('%task' => $task['function'])));
-        }
-      }
-    }
-    // Check for failed results and compile message
-    $message = '';
-    foreach ($this->results as $result => $success) {
-      if (!$success) {
-        $message .= '<p class="error">' . $result  . '</p>';
-      }
-    }
-    if (!empty($message)) {
-      $message = '<p>In order for Drupal to work, and to continue with the installation process, you must resolve all issues reported below. For more help with configuring your database server, see the <a href="http://drupal.org/getting-started/install">installation handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.</p>' . $message;
-      throw new DatabaseTaskException($message);
-    }
-  }
-
-  /**
-   * Check if we can connect to the database.
-   */
-  protected function connect() {
-    try {
-      // This doesn't actually test the connection.
-      db_set_active();
-      // Now actually do a check.
-      Database::getConnection();
-      $this->pass('Drupal can CONNECT to the database ok.');
-    }
-    catch (Exception $e) {
-      $this->fail(st('Failed to connect to your database server. The server reports the following message: %error.<ul><li>Is the database server running?</li><li>Does the database exist, and have you entered the correct database name?</li><li>Have you entered the correct username and password?</li><li>Have you entered the correct database hostname?</li></ul>', array('%error' => $e->getMessage())));
-      return FALSE;
-    }
-    return TRUE;
-  }
-
-  /**
-   * Run SQL tests to ensure the database can execute commands with the current user.
-   */
-  protected function runTestQuery($query, $pass, $fail, $fatal = FALSE) {
-    try {
-      db_query($query);
-      $this->pass(st($pass));
-    }
-    catch (Exception $e) {
-      $this->fail(st($fail, array('%query' => $query, '%error' => $e->getMessage(), '%name' => $this->name())));
-      return !$fatal;
-    }
-  }
-
-  /**
-   * Check the engine version.
-   */
-  protected function checkEngineVersion() {
-    if ($this->minimumVersion() && version_compare(Database::getConnection()->version(), $this->minimumVersion(), '<')) {
-      $this->fail(st("The database version %version is less than the minimum required version %minimum_version.", array('%version' => Database::getConnection()->version(), '%minimum_version' => $this->minimumVersion())));
-    }
-  }
-
-  /**
-   * Return driver specific configuration options.
-   *
-   * @param $database
-   *  An array of driver specific configuration options.
-   *
-   * @return
-   *   The options form array.
-   */
-  public function getFormOptions($database) {
-    $form['database'] = array(
-      '#type' => 'textfield',
-      '#title' => st('Database name'),
-      '#default_value' => empty($database['database']) ? '' : $database['database'],
-      '#size' => 45,
-      '#required' => TRUE,
-      '#description' => st('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => drupal_install_profile_distribution_name())),
-    );
-
-    $form['username'] = array(
-      '#type' => 'textfield',
-      '#title' => st('Database username'),
-      '#default_value' => empty($database['username']) ? '' : $database['username'],
-      '#required' => TRUE,
-      '#size' => 45,
-    );
-
-    $form['password'] = array(
-      '#type' => 'password',
-      '#title' => st('Database password'),
-      '#default_value' => empty($database['password']) ? '' : $database['password'],
-      '#required' => FALSE,
-      '#size' => 45,
-    );
-
-    $form['advanced_options'] = array(
-      '#type' => 'fieldset',
-      '#title' => st('Advanced options'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-      '#description' => st("These options are only necessary for some sites. If you're not sure what you should enter here, leave the default settings or check with your hosting provider."),
-      '#weight' => 10,
-    );
-
-    $profile = drupal_get_profile();
-    $db_prefix = ($profile == 'standard') ? 'drupal_' : $profile . '_';
-    $form['advanced_options']['db_prefix'] = array(
-      '#type' => 'textfield',
-      '#title' => st('Table prefix'),
-      '#default_value' => '',
-      '#size' => 45,
-      '#description' => st('If more than one application will be sharing this database, enter a table prefix such as %prefix for your @drupal site here.', array('@drupal' => drupal_install_profile_distribution_name(), '%prefix' => $db_prefix)),
-      '#weight' => 10,
-    );
-
-    $form['advanced_options']['host'] = array(
-      '#type' => 'textfield',
-      '#title' => st('Database host'),
-      '#default_value' => empty($database['host']) ? 'localhost' : $database['host'],
-      '#size' => 45,
-      // Hostnames can be 255 characters long.
-      '#maxlength' => 255,
-      '#required' => TRUE,
-      '#description' => st('If your database is located on a different server, change this.'),
-    );
-
-    $form['advanced_options']['port'] = array(
-      '#type' => 'textfield',
-      '#title' => st('Database port'),
-      '#default_value' => empty($database['port']) ? '' : $database['port'],
-      '#size' => 45,
-      // The maximum port number is 65536, 5 digits.
-      '#maxlength' => 5,
-      '#description' => st('If your database server is listening to a non-standard port, enter its number.'),
-    );
-
-    return $form;
-  }
-
-  /**
-   * Validates driver specific configuration settings.
-   *
-   * Checks to ensure correct basic database settings and that a proper
-   * connection to the database can be established.
-   *
-   * @param $database
-   *   An array of driver specific configuration options.
-   *
-   * @return
-   *   An array of driver configuration errors, keyed by form element name.
-   */
-  public function validateDatabaseSettings($database) {
-    $errors = array();
-
-    // Verify the table prefix.
-    if (!empty($database['prefix']) && is_string($database['prefix']) && !preg_match('/^[A-Za-z0-9_.]+$/', $database['prefix'])) {
-      $errors[$database['driver'] . '][advanced_options][db_prefix'] = st('The database table prefix you have entered, %prefix, is invalid. The table prefix can only contain alphanumeric characters, periods, or underscores.', array('%prefix' => $database['prefix']));
-    }
-
-    // Verify the database port.
-    if (!empty($database['port']) && !is_numeric($database['port'])) {
-      $errors[$database['driver'] . '][advanced_options][port'] =  st('Database port must be a number.');
-    }
-
-    return $errors;
-  }
-
-}
-
-/**
- * Exception thrown if the database installer fails.
- */
-class DatabaseTaskException extends Exception {
-}
-
 /**
  * Replace values in settings.php with values in the submitted array.
  *
@@ -1301,7 +1005,8 @@ function db_run_tasks($driver) {
  *   The name of the driver.
  */
 function db_installer_object($driver) {
-  Database::loadDriverFile($driver, array('install.inc'));
-  $task_class = 'DatabaseTasks_' . $driver;
+  // We cannot use Database::getConnection->getDriverClass() here, because
+  // the connection object is not yet functional.
+  $task_class = "Drupal\\Core\\Database\\Driver\\{$driver}\\Install\\Tasks";
   return new $task_class();
 }
diff --git a/core/includes/pager.inc b/core/includes/pager.inc
index c060d0e7cda526b514e3ac999a01e789151ca412..c579e7e64809c81f9df08dfbbef9424a291a15a5 100644
--- a/core/includes/pager.inc
+++ b/core/includes/pager.inc
@@ -1,18 +1,21 @@
 <?php
 
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Query\SelectExtender;
+use Drupal\Core\Database\Query\SelectInterface;
+
 /**
  * @file
  * Functions to aid in presenting database results as a set of pages.
  */
 
-
 /**
  * Query extender for pager queries.
  *
  * This is the "default" pager mechanism.  It creates a paged query with a fixed
  * number of entries per page.
  */
-class PagerDefault extends SelectQueryExtender {
+class PagerDefault extends SelectExtender {
 
   /**
    * The highest element we've autogenerated so far.
@@ -42,7 +45,7 @@ class PagerDefault extends SelectQueryExtender {
    */
   protected $customCountQuery = FALSE;
 
-  public function __construct(SelectQueryInterface $query, DatabaseConnection $connection) {
+  public function __construct(SelectInterface $query, Connection $connection) {
     parent::__construct($query, $connection);
 
     // Add pager tag. Do this here to ensure that it is always added before
@@ -103,7 +106,7 @@ protected function ensureElement() {
    *   The count query object.  It must return a single row with a single column,
    *   which is the total number of records.
    */
-  public function setCountQuery(SelectQueryInterface $query) {
+  public function setCountQuery(SelectInterface $query) {
     $this->customCountQuery = $query;
   }
 
diff --git a/core/includes/registry.inc b/core/includes/registry.inc
index 2ddd1f7f70a8d90333911d10a20f91d49a12420f..7ac296017942aca8c1d0245829dfda4333399681 100644
--- a/core/includes/registry.inc
+++ b/core/includes/registry.inc
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * @file
  * This file contains the code registry parser engine.
@@ -20,18 +22,12 @@
  */
 function _registry_update() {
 
-  // The registry serves as a central autoloader for all classes, including
-  // the database query builders. However, the registry rebuild process
-  // requires write ability to the database, which means having access to the
-  // query builders that require the registry in order to be loaded. That
-  // causes a fatal race condition. Therefore we manually include the
-  // appropriate query builders for the currently active database before the
-  // registry rebuild process runs.
+  // The registry serves as a central autoloader for all non-namespaced classes.
+  // It is backed by the database, but the database system is autoloaded using
+  // a PSR-0 class loader.  That avoids a fata circular dependency here, since
+  // the other class loader will be able to load the database for us.
   $connection_info = Database::getConnectionInfo();
   $driver = $connection_info['default']['driver'];
-  require_once DRUPAL_ROOT . '/core/includes/database/query.inc';
-  require_once DRUPAL_ROOT . '/core/includes/database/select.inc';
-  require_once DRUPAL_ROOT . '/core/includes/database/' . $driver . '/query.inc';
 
   // Get current list of modules and their files.
   $modules = db_query("SELECT * FROM {system} WHERE type = 'module'")->fetchAll();
diff --git a/core/includes/tablesort.inc b/core/includes/tablesort.inc
index 7873cdb2db42f2aba2a6f0ae876f7ffb7c02def2..3c70b965c30a0df9757022dd3cb2dfa2d79d0d29 100644
--- a/core/includes/tablesort.inc
+++ b/core/includes/tablesort.inc
@@ -1,5 +1,9 @@
 <?php
 
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Query\SelectExtender;
+use Drupal\Core\Database\Query\SelectInterface;
+
 /**
  * @file
  * Functions to aid in the creation of sortable tables.
@@ -8,11 +12,10 @@
  * column headers that the user can click on to sort the table by that column.
  */
 
-
 /**
  * Query extender class for tablesort queries.
  */
-class TableSort extends SelectQueryExtender {
+class TableSort extends SelectExtender {
 
   /**
    * The array of fields that can be sorted by.
@@ -21,7 +24,7 @@ class TableSort extends SelectQueryExtender {
    */
   protected $header = array();
 
-  public function __construct(SelectQueryInterface $query, DatabaseConnection $connection) {
+  public function __construct(SelectInterface $query, Connection $connection) {
     parent::__construct($query, $connection);
 
     // Add convenience tag to mark that this is an extended query. We have to
diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php
new file mode 100644
index 0000000000000000000000000000000000000000..6e9e44aec14605fc8b6f902a49e2937ef0b03126
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -0,0 +1,1126 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Connection
+ */
+
+namespace Drupal\Core\Database;
+
+use Drupal\Core\Database\TransactionNoActiveException;
+use Drupal\Core\Database\TransactionOutOfOrderException;
+
+use PDO;
+use PDOException;
+
+/**
+ * Base Database API class.
+ *
+ * This class provides a Drupal-specific extension of the PDO database
+ * abstraction class in PHP. Every database driver implementation must provide a
+ * concrete implementation of it to support special handling required by that
+ * database.
+ *
+ * @see http://php.net/manual/en/book.pdo.php
+ */
+abstract class Connection extends PDO {
+
+  /**
+   * The database target this connection is for.
+   *
+   * We need this information for later auditing and logging.
+   *
+   * @var string
+   */
+  protected $target = NULL;
+
+  /**
+   * The key representing this connection.
+   *
+   * The key is a unique string which identifies a database connection. A
+   * connection can be a single server or a cluster of master and slaves (use
+   * target to pick between master and slave).
+   *
+   * @var string
+   */
+  protected $key = NULL;
+
+  /**
+   * The current database logging object for this connection.
+   *
+   * @var Log
+   */
+  protected $logger = NULL;
+
+  /**
+   * Tracks the number of "layers" of transactions currently active.
+   *
+   * On many databases transactions cannot nest.  Instead, we track
+   * nested calls to transactions and collapse them into a single
+   * transaction.
+   *
+   * @var array
+   */
+  protected $transactionLayers = array();
+
+  /**
+   * Index of what driver-specific class to use for various operations.
+   *
+   * @var array
+   */
+  protected $driverClasses = array();
+
+  /**
+   * The name of the Statement class for this connection.
+   *
+   * @var string
+   */
+  protected $statementClass = 'Drupal\Core\Database\Statement';
+
+  /**
+   * Whether this database connection supports transactions.
+   *
+   * @var bool
+   */
+  protected $transactionSupport = TRUE;
+
+  /**
+   * Whether this database connection supports transactional DDL.
+   *
+   * Set to FALSE by default because few databases support this feature.
+   *
+   * @var bool
+   */
+  protected $transactionalDDLSupport = FALSE;
+
+  /**
+   * An index used to generate unique temporary table names.
+   *
+   * @var integer
+   */
+  protected $temporaryNameIndex = 0;
+
+  /**
+   * The connection information for this connection object.
+   *
+   * @var array
+   */
+  protected $connectionOptions = array();
+
+  /**
+   * The schema object for this connection.
+   *
+   * @var object
+   */
+  protected $schema = NULL;
+
+  /**
+   * The prefixes used by this database connection.
+   *
+   * @var array
+   */
+  protected $prefixes = array();
+
+  /**
+   * List of search values for use in prefixTables().
+   *
+   * @var array
+   */
+  protected $prefixSearch = array();
+
+  /**
+   * List of replacement values for use in prefixTables().
+   *
+   * @var array
+   */
+  protected $prefixReplace = array();
+
+  function __construct($dsn, $username, $password, $driver_options = array()) {
+    // Initialize and prepare the connection prefix.
+    $this->setPrefix(isset($this->connectionOptions['prefix']) ? $this->connectionOptions['prefix'] : '');
+
+    // Because the other methods don't seem to work right.
+    $driver_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
+
+    // Call PDO::__construct and PDO::setAttribute.
+    parent::__construct($dsn, $username, $password, $driver_options);
+
+    // Set a specific PDOStatement class if the driver requires that.
+    if (!empty($this->statementClass)) {
+      $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this)));
+    }
+  }
+
+  /**
+   * Returns the default query options for any given query.
+   *
+   * A given query can be customized with a number of option flags in an
+   * associative array:
+   * - target: The database "target" against which to execute a query. Valid
+   *   values are "default" or "slave". The system will first try to open a
+   *   connection to a database specified with the user-supplied key. If one
+   *   is not available, it will silently fall back to the "default" target.
+   *   If multiple databases connections are specified with the same target,
+   *   one will be selected at random for the duration of the request.
+   * - fetch: This element controls how rows from a result set will be
+   *   returned. Legal values include PDO::FETCH_ASSOC, PDO::FETCH_BOTH,
+   *   PDO::FETCH_OBJ, PDO::FETCH_NUM, or a string representing the name of a
+   *   class. If a string is specified, each record will be fetched into a new
+   *   object of that class. The behavior of all other values is defined by PDO.
+   *   See http://php.net/manual/pdostatement.fetch.php
+   * - return: Depending on the type of query, different return values may be
+   *   meaningful. This directive instructs the system which type of return
+   *   value is desired. The system will generally set the correct value
+   *   automatically, so it is extremely rare that a module developer will ever
+   *   need to specify this value. Setting it incorrectly will likely lead to
+   *   unpredictable results or fatal errors. Legal values include:
+   *   - Database::RETURN_STATEMENT: Return the prepared statement object for
+   *     the query. This is usually only meaningful for SELECT queries, where
+   *     the statement object is how one accesses the result set returned by the
+   *     query.
+   *   - Database::RETURN_AFFECTED: Return the number of rows affected by an
+   *     UPDATE or DELETE query. Be aware that means the number of rows actually
+   *     changed, not the number of rows matched by the WHERE clause.
+   *   - Database::RETURN_INSERT_ID: Return the sequence ID (primary key)
+   *     created by an INSERT statement on a table that contains a serial
+   *     column.
+   *   - Database::RETURN_NULL: Do not return anything, as there is no
+   *     meaningful value to return. That is the case for INSERT queries on
+   *     tables that do not contain a serial column.
+   * - throw_exception: By default, the database system will catch any errors
+   *   on a query as an Exception, log it, and then rethrow it so that code
+   *   further up the call chain can take an appropriate action. To suppress
+   *   that behavior and simply return NULL on failure, set this option to
+   *   FALSE.
+   *
+   * @return
+   *   An array of default query options.
+   */
+  protected function defaultOptions() {
+    return array(
+      'target' => 'default',
+      'fetch' => PDO::FETCH_OBJ,
+      'return' => Database::RETURN_STATEMENT,
+      'throw_exception' => TRUE,
+    );
+  }
+
+  /**
+   * Returns the connection information for this connection object.
+   *
+   * Note that Database::getConnectionInfo() is for requesting information
+   * about an arbitrary database connection that is defined. This method
+   * is for requesting the connection information of this specific
+   * open connection object.
+   *
+   * @return
+   *   An array of the connection information. The exact list of
+   *   properties is driver-dependent.
+   */
+  public function getConnectionOptions() {
+    return $this->connectionOptions;
+  }
+
+  /**
+   * Set the list of prefixes used by this database connection.
+   *
+   * @param $prefix
+   *   The prefixes, in any of the multiple forms documented in
+   *   default.settings.php.
+   */
+  protected function setPrefix($prefix) {
+    if (is_array($prefix)) {
+      $this->prefixes = $prefix + array('default' => '');
+    }
+    else {
+      $this->prefixes = array('default' => $prefix);
+    }
+
+    // Set up variables for use in prefixTables(). Replace table-specific
+    // prefixes first.
+    $this->prefixSearch = array();
+    $this->prefixReplace = array();
+    foreach ($this->prefixes as $key => $val) {
+      if ($key != 'default') {
+        $this->prefixSearch[] = '{' . $key . '}';
+        $this->prefixReplace[] = $val . $key;
+      }
+    }
+    // Then replace remaining tables with the default prefix.
+    $this->prefixSearch[] = '{';
+    $this->prefixReplace[] = $this->prefixes['default'];
+    $this->prefixSearch[] = '}';
+    $this->prefixReplace[] = '';
+  }
+
+  /**
+   * Appends a database prefix to all tables in a query.
+   *
+   * Queries sent to Drupal should wrap all table names in curly brackets. This
+   * function searches for this syntax and adds Drupal's table prefix to all
+   * tables, allowing Drupal to coexist with other systems in the same database
+   * and/or schema if necessary.
+   *
+   * @param $sql
+   *   A string containing a partial or entire SQL query.
+   *
+   * @return
+   *   The properly-prefixed string.
+   */
+  public function prefixTables($sql) {
+    return str_replace($this->prefixSearch, $this->prefixReplace, $sql);
+  }
+
+  /**
+   * Find the prefix for a table.
+   *
+   * This function is for when you want to know the prefix of a table. This
+   * is not used in prefixTables due to performance reasons.
+   */
+  public function tablePrefix($table = 'default') {
+    if (isset($this->prefixes[$table])) {
+      return $this->prefixes[$table];
+    }
+    else {
+      return $this->prefixes['default'];
+    }
+  }
+
+  /**
+   * Prepares a query string and returns the prepared statement.
+   *
+   * This method caches prepared statements, reusing them when
+   * possible. It also prefixes tables names enclosed in curly-braces.
+   *
+   * @param $query
+   *   The query string as SQL, with curly-braces surrounding the
+   *   table names.
+   *
+   * @return Drupal\Core\Database\StatementInterface
+   *   A PDO prepared statement ready for its execute() method.
+   */
+  public function prepareQuery($query) {
+    $query = $this->prefixTables($query);
+
+    // Call PDO::prepare.
+    return parent::prepare($query);
+  }
+
+  /**
+   * Tells this connection object what its target value is.
+   *
+   * This is needed for logging and auditing. It's sloppy to do in the
+   * constructor because the constructor for child classes has a different
+   * signature. We therefore also ensure that this function is only ever
+   * called once.
+   *
+   * @param $target
+   *   The target this connection is for. Set to NULL (default) to disable
+   *   logging entirely.
+   */
+  public function setTarget($target = NULL) {
+    if (!isset($this->target)) {
+      $this->target = $target;
+    }
+  }
+
+  /**
+   * Returns the target this connection is associated with.
+   *
+   * @return
+   *   The target string of this connection.
+   */
+  public function getTarget() {
+    return $this->target;
+  }
+
+  /**
+   * Tells this connection object what its key is.
+   *
+   * @param $target
+   *   The key this connection is for.
+   */
+  public function setKey($key) {
+    if (!isset($this->key)) {
+      $this->key = $key;
+    }
+  }
+
+  /**
+   * Returns the key this connection is associated with.
+   *
+   * @return
+   *   The key of this connection.
+   */
+  public function getKey() {
+    return $this->key;
+  }
+
+  /**
+   * Associates a logging object with this connection.
+   *
+   * @param $logger
+   *   The logging object we want to use.
+   */
+  public function setLogger(Log $logger) {
+    $this->logger = $logger;
+  }
+
+  /**
+   * Gets the current logging object for this connection.
+   *
+   * @return DatabaseLog
+   *   The current logging object for this connection. If there isn't one,
+   *   NULL is returned.
+   */
+  public function getLogger() {
+    return $this->logger;
+  }
+
+  /**
+   * Creates the appropriate sequence name for a given table and serial field.
+   *
+   * This information is exposed to all database drivers, although it is only
+   * useful on some of them. This method is table prefix-aware.
+   *
+   * @param $table
+   *   The table name to use for the sequence.
+   * @param $field
+   *   The field name to use for the sequence.
+   *
+   * @return
+   *   A table prefix-parsed string for the sequence name.
+   */
+  public function makeSequenceName($table, $field) {
+    return $this->prefixTables('{' . $table . '}_' . $field . '_seq');
+  }
+
+  /**
+   * Flatten an array of query comments into a single comment string.
+   *
+   * The comment string will be sanitized to avoid SQL injection attacks.
+   *
+   * @param $comments
+   *   An array of query comment strings.
+   *
+   * @return
+   *   A sanitized comment string.
+   */
+  public function makeComment($comments) {
+    if (empty($comments))
+      return '';
+
+    // Flatten the array of comments.
+    $comment = implode('; ', $comments);
+
+    // Sanitize the comment string so as to avoid SQL injection attacks.
+    return '/* ' . $this->filterComment($comment) . ' */ ';
+  }
+
+  /**
+   * Sanitize a query comment string.
+   *
+   * Ensure a query comment does not include strings such as "* /" that might
+   * terminate the comment early. This avoids SQL injection attacks via the
+   * query comment. The comment strings in this example are separated by a
+   * space to avoid PHP parse errors.
+   *
+   * For example, the comment:
+   * @code
+   * db_update('example')
+   *  ->condition('id', $id)
+   *  ->fields(array('field2' => 10))
+   *  ->comment('Exploit * / DROP TABLE node; --')
+   *  ->execute()
+   * @endcode
+   *
+   * Would result in the following SQL statement being generated:
+   * @code
+   * "/ * Exploit * / DROP TABLE node; -- * / UPDATE example SET field2=..."
+   * @endcode
+   *
+   * Unless the comment is sanitised first, the SQL server would drop the
+   * node table and ignore the rest of the SQL statement.
+   *
+   * @param $comment
+   *   A query comment string.
+   *
+   * @return
+   *   A sanitized version of the query comment string.
+   */
+  protected function filterComment($comment = '') {
+    return preg_replace('/(\/\*\s*)|(\s*\*\/)/', '', $comment);
+  }
+
+  /**
+   * Executes a query string against the database.
+   *
+   * This method provides a central handler for the actual execution of every
+   * query. All queries executed by Drupal are executed as PDO prepared
+   * statements.
+   *
+   * @param $query
+   *   The query to execute. In most cases this will be a string containing
+   *   an SQL query with placeholders. An already-prepared instance of
+   *   DatabaseStatementInterface may also be passed in order to allow calling
+   *   code to manually bind variables to a query. If a
+   *   DatabaseStatementInterface is passed, the $args array will be ignored.
+   *   It is extremely rare that module code will need to pass a statement
+   *   object to this method. It is used primarily for database drivers for
+   *   databases that require special LOB field handling.
+   * @param $args
+   *   An array of arguments for the prepared statement. If the prepared
+   *   statement uses ? placeholders, this array must be an indexed array.
+   *   If it contains named placeholders, it must be an associative array.
+   * @param $options
+   *   An associative array of options to control how the query is run. See
+   *   the documentation for DatabaseConnection::defaultOptions() for details.
+   *
+   * @return Drupal\Core\Database\StatementInterface
+   *   This method will return one of: the executed statement, the number of
+   *   rows affected by the query (not the number matched), or the generated
+   *   insert IT of the last query, depending on the value of
+   *   $options['return']. Typically that value will be set by default or a
+   *   query builder and should not be set by a user. If there is an error,
+   *   this method will return NULL and may throw an exception if
+   *   $options['throw_exception'] is TRUE.
+   *
+   * @throws PDOException
+   */
+  public function query($query, array $args = array(), $options = array()) {
+
+    // Use default values if not already set.
+    $options += $this->defaultOptions();
+
+    try {
+      // We allow either a pre-bound statement object or a literal string.
+      // In either case, we want to end up with an executed statement object,
+      // which we pass to PDOStatement::execute.
+      if ($query instanceof DatabaseStatementInterface) {
+        $stmt = $query;
+        $stmt->execute(NULL, $options);
+      }
+      else {
+        $this->expandArguments($query, $args);
+        $stmt = $this->prepareQuery($query);
+        $stmt->execute($args, $options);
+      }
+
+      // Depending on the type of query we may need to return a different value.
+      // See DatabaseConnection::defaultOptions() for a description of each
+      // value.
+      switch ($options['return']) {
+        case Database::RETURN_STATEMENT:
+          return $stmt;
+        case Database::RETURN_AFFECTED:
+          return $stmt->rowCount();
+        case Database::RETURN_INSERT_ID:
+          return $this->lastInsertId();
+        case Database::RETURN_NULL:
+          return;
+        default:
+          throw new PDOException('Invalid return directive: ' . $options['return']);
+      }
+    }
+    catch (PDOException $e) {
+      if ($options['throw_exception']) {
+        // Add additional debug information.
+        if ($query instanceof DatabaseStatementInterface) {
+          $e->query_string = $stmt->getQueryString();
+        }
+        else {
+          $e->query_string = $query;
+        }
+        $e->args = $args;
+        throw $e;
+      }
+      return NULL;
+    }
+  }
+
+  /**
+   * Expands out shorthand placeholders.
+   *
+   * Drupal supports an alternate syntax for doing arrays of values. We
+   * therefore need to expand them out into a full, executable query string.
+   *
+   * @param $query
+   *   The query string to modify.
+   * @param $args
+   *   The arguments for the query.
+   *
+   * @return
+   *   TRUE if the query was modified, FALSE otherwise.
+   */
+  protected function expandArguments(&$query, &$args) {
+    $modified = FALSE;
+
+    // If the placeholder value to insert is an array, assume that we need
+    // to expand it out into a comma-delimited set of placeholders.
+    foreach (array_filter($args, 'is_array') as $key => $data) {
+      $new_keys = array();
+      foreach ($data as $i => $value) {
+        // This assumes that there are no other placeholders that use the same
+        // name.  For example, if the array placeholder is defined as :example
+        // and there is already an :example_2 placeholder, this will generate
+        // a duplicate key.  We do not account for that as the calling code
+        // is already broken if that happens.
+        $new_keys[$key . '_' . $i] = $value;
+      }
+
+      // Update the query with the new placeholders.
+      // preg_replace is necessary to ensure the replacement does not affect
+      // placeholders that start with the same exact text. For example, if the
+      // query contains the placeholders :foo and :foobar, and :foo has an
+      // array of values, using str_replace would affect both placeholders,
+      // but using the following preg_replace would only affect :foo because
+      // it is followed by a non-word character.
+      $query = preg_replace('#' . $key . '\b#', implode(', ', array_keys($new_keys)), $query);
+
+      // Update the args array with the new placeholders.
+      unset($args[$key]);
+      $args += $new_keys;
+
+      $modified = TRUE;
+    }
+
+    return $modified;
+  }
+
+  /**
+   * Gets the driver-specific override class if any for the specified class.
+   *
+   * @param string $class
+   *   The class for which we want the potentially driver-specific class.
+   * @return string
+   *   The name of the class that should be used for this driver.
+   */
+  public function getDriverClass($class) {
+    if (empty($this->driverClasses[$class])) {
+      $driver = $this->driver();
+      $driver_class = "Drupal\\Core\\Database\\Driver\\{$driver}\\{$class}";
+      $this->driverClasses[$class] = class_exists($driver_class) ? $driver_class : $class;
+    }
+    return $this->driverClasses[$class];
+  }
+
+  /**
+   * Prepares and returns a SELECT query object.
+   *
+   * @param $table
+   *   The base table for this query, that is, the first table in the FROM
+   *   clause. This table will also be used as the "base" table for query_alter
+   *   hook implementations.
+   * @param $alias
+   *   The alias of the base table of this query.
+   * @param $options
+   *   An array of options on the query.
+   *
+   * @return Drupal\Core\Database\Query\SelectInterface
+   *   An appropriate SelectQuery object for this database connection. Note that
+   *   it may be a driver-specific subclass of SelectQuery, depending on the
+   *   driver.
+   *
+   * @see Drupal\Core\Database\Query\Select
+   */
+  public function select($table, $alias = NULL, array $options = array()) {
+    $class = $this->getDriverClass('Select');
+    return new $class($table, $alias, $this, $options);
+  }
+
+  /**
+   * Prepares and returns an INSERT query object.
+   *
+   * @param $options
+   *   An array of options on the query.
+   *
+   * @return Drupal\Core\Database\Query\Insert
+   *   A new Insert query object.
+   *
+   * @see Drupal\Core\Database\Query\Insert
+   */
+  public function insert($table, array $options = array()) {
+    $class = $this->getDriverClass('Insert');
+    return new $class($this, $table, $options);
+  }
+
+  /**
+   * Prepares and returns a MERGE query object.
+   *
+   * @param $options
+   *   An array of options on the query.
+   *
+   * @return Drupal\Core\Database\Query\Merge
+   *   A new Merge query object.
+   *
+   * @see Drupal\Core\Database\Query\Merge
+   */
+  public function merge($table, array $options = array()) {
+    $class = $this->getDriverClass('Merge');
+    return new $class($this, $table, $options);
+  }
+
+
+  /**
+   * Prepares and returns an UPDATE query object.
+   *
+   * @param $options
+   *   An array of options on the query.
+   *
+   * @return Drupal\Core\Database\Query\Update
+   *   A new Update query object.
+   *
+   * @see Drupal\Core\Database\Query\Update
+   */
+  public function update($table, array $options = array()) {
+    $class = $this->getDriverClass('Update');
+    return new $class($this, $table, $options);
+  }
+
+  /**
+   * Prepares and returns a DELETE query object.
+   *
+   * @param $options
+   *   An array of options on the query.
+   *
+   * @return Drupal\Core\Database\Query\Delete
+   *   A new Delete query object.
+   *
+   * @see Drupal\Core\Database\Query\Delete
+   */
+  public function delete($table, array $options = array()) {
+    $class = $this->getDriverClass('Delete');
+    return new $class($this, $table, $options);
+  }
+
+  /**
+   * Prepares and returns a TRUNCATE query object.
+   *
+   * @param $options
+   *   An array of options on the query.
+   *
+   * @return Drupal\Core\Database\Query\Truncate
+   *   A new Truncate query object.
+   *
+   * @see Drupal\Core\Database\Query\Truncate
+   */
+  public function truncate($table, array $options = array()) {
+    $class = $this->getDriverClass('Truncate');
+    return new $class($this, $table, $options);
+  }
+
+  /**
+   * Returns a DatabaseSchema object for manipulating the schema.
+   *
+   * This method will lazy-load the appropriate schema library file.
+   *
+   * @return Drupal\Core\Database\Schema
+   *   The database Schema object for this connection.
+   */
+  public function schema() {
+    if (empty($this->schema)) {
+      $class = $this->getDriverClass('Schema');
+      $this->schema = new $class($this);
+    }
+    return $this->schema;
+  }
+
+  /**
+   * Escapes a table name string.
+   *
+   * Force all table names to be strictly alphanumeric-plus-underscore.
+   * For some database drivers, it may also wrap the table name in
+   * database-specific escape characters.
+   *
+   * @return
+   *   The sanitized table name string.
+   */
+  public function escapeTable($table) {
+    return preg_replace('/[^A-Za-z0-9_.]+/', '', $table);
+  }
+
+  /**
+   * Escapes a field name string.
+   *
+   * Force all field names to be strictly alphanumeric-plus-underscore.
+   * For some database drivers, it may also wrap the field name in
+   * database-specific escape characters.
+   *
+   * @return
+   *   The sanitized field name string.
+   */
+  public function escapeField($field) {
+    return preg_replace('/[^A-Za-z0-9_.]+/', '', $field);
+  }
+
+  /**
+   * Escapes an alias name string.
+   *
+   * Force all alias names to be strictly alphanumeric-plus-underscore. In
+   * contrast to DatabaseConnection::escapeField() /
+   * DatabaseConnection::escapeTable(), this doesn't allow the period (".")
+   * because that is not allowed in aliases.
+   *
+   * @return
+   *   The sanitized field name string.
+   */
+  public function escapeAlias($field) {
+    return preg_replace('/[^A-Za-z0-9_]+/', '', $field);
+  }
+
+  /**
+   * Escapes characters that work as wildcard characters in a LIKE pattern.
+   *
+   * The wildcard characters "%" and "_" as well as backslash are prefixed with
+   * a backslash. Use this to do a search for a verbatim string without any
+   * wildcard behavior.
+   *
+   * For example, the following does a case-insensitive query for all rows whose
+   * name starts with $prefix:
+   * @code
+   * $result = db_query(
+   *   'SELECT * FROM person WHERE name LIKE :pattern',
+   *   array(':pattern' => db_like($prefix) . '%')
+   * );
+   * @endcode
+   *
+   * Backslash is defined as escape character for LIKE patterns in
+   * Drupal\Core\Database\Query\Condition::mapConditionOperator().
+   *
+   * @param $string
+   *   The string to escape.
+   *
+   * @return
+   *   The escaped string.
+   */
+  public function escapeLike($string) {
+    return addcslashes($string, '\%_');
+  }
+
+  /**
+   * Determines if there is an active transaction open.
+   *
+   * @return
+   *   TRUE if we're currently in a transaction, FALSE otherwise.
+   */
+  public function inTransaction() {
+    return ($this->transactionDepth() > 0);
+  }
+
+  /**
+   * Determines current transaction depth.
+   */
+  public function transactionDepth() {
+    return count($this->transactionLayers);
+  }
+
+  /**
+   * Returns a new DatabaseTransaction object on this connection.
+   *
+   * @param $name
+   *   Optional name of the savepoint.
+   *
+   * @see Drupal\Core\Database\Transaction
+   */
+  public function startTransaction($name = '') {
+    $class = $this->getDriverClass('Transaction');
+    return new $class($this, $name);
+  }
+
+  /**
+   * Rolls back the transaction entirely or to a named savepoint.
+   *
+   * This method throws an exception if no transaction is active.
+   *
+   * @param $savepoint_name
+   *   The name of the savepoint. The default, 'drupal_transaction', will roll
+   *   the entire transaction back.
+   *
+   * @throws Drupal\Core\Database\TransactionNoActiveException
+   *
+   * @see DatabaseTransaction::rollback()
+   */
+  public function rollback($savepoint_name = 'drupal_transaction') {
+    if (!$this->supportsTransactions()) {
+      return;
+    }
+    if (!$this->inTransaction()) {
+      throw new TransactionNoActiveException();
+    }
+    // A previous rollback to an earlier savepoint may mean that the savepoint
+    // in question has already been accidentally committed.
+    if (!isset($this->transactionLayers[$savepoint_name])) {
+      throw new TransactionNoActiveException();
+     }
+
+    // We need to find the point we're rolling back to, all other savepoints
+    // before are no longer needed. If we rolled back other active savepoints,
+    // we need to throw an exception.
+    $rolled_back_other_active_savepoints = FALSE;
+    while ($savepoint = array_pop($this->transactionLayers)) {
+      if ($savepoint == $savepoint_name) {
+        // If it is the last the transaction in the stack, then it is not a
+        // savepoint, it is the transaction itself so we will need to roll back
+        // the transaction rather than a savepoint.
+        if (empty($this->transactionLayers)) {
+          break;
+        }
+        $this->query('ROLLBACK TO SAVEPOINT ' . $savepoint);
+        $this->popCommittableTransactions();
+        if ($rolled_back_other_active_savepoints) {
+          throw new TransactionOutOfOrderException();
+        }
+        return;
+      }
+      else {
+        $rolled_back_other_active_savepoints = TRUE;
+      }
+    }
+    parent::rollBack();
+    if ($rolled_back_other_active_savepoints) {
+      throw new TransactionOutOfOrderException();
+    }
+  }
+
+  /**
+   * Increases the depth of transaction nesting.
+   *
+   * If no transaction is already active, we begin a new transaction.
+   *
+   * @throws Drupal\Core\Database\TransactionNameNonUniqueException
+   *
+   * @see Drupal\Core\Database\Transaction
+   */
+  public function pushTransaction($name) {
+    if (!$this->supportsTransactions()) {
+      return;
+    }
+    if (isset($this->transactionLayers[$name])) {
+      throw new TransactionNameNonUniqueException($name . " is already in use.");
+    }
+    // If we're already in a transaction then we want to create a savepoint
+    // rather than try to create another transaction.
+    if ($this->inTransaction()) {
+      $this->query('SAVEPOINT ' . $name);
+    }
+    else {
+      parent::beginTransaction();
+    }
+    $this->transactionLayers[$name] = $name;
+  }
+
+  /**
+   * Decreases the depth of transaction nesting.
+   *
+   * If we pop off the last transaction layer, then we either commit or roll
+   * back the transaction as necessary. If no transaction is active, we return
+   * because the transaction may have manually been rolled back.
+   *
+   * @param $name
+   *   The name of the savepoint
+   *
+   * @throws Drupal\Core\Database\TransactionNoActiveException
+   * @throws Drupal\Core\Database\TransactionCommitFailedException
+   *
+   * @see DatabaseTransaction
+   */
+  public function popTransaction($name) {
+    if (!$this->supportsTransactions()) {
+      return;
+    }
+    // The transaction has already been committed earlier. There is nothing we
+    // need to do. If this transaction was part of an earlier out-of-order
+    // rollback, an exception would already have been thrown by
+    // Database::rollback().
+    if (!isset($this->transactionLayers[$name])) {
+      return;
+    }
+
+    // Mark this layer as committable.
+    $this->transactionLayers[$name] = FALSE;
+    $this->popCommittableTransactions();
+  }
+
+  /**
+   * Internal function: commit all the transaction layers that can commit.
+   */
+  protected function popCommittableTransactions() {
+    // Commit all the committable layers.
+    foreach (array_reverse($this->transactionLayers) as $name => $active) {
+      // Stop once we found an active transaction.
+      if ($active) {
+        break;
+      }
+
+      // If there are no more layers left then we should commit.
+      unset($this->transactionLayers[$name]);
+      if (empty($this->transactionLayers)) {
+        if (!parent::commit()) {
+          throw new TransactionCommitFailedException();
+        }
+      }
+      else {
+        $this->query('RELEASE SAVEPOINT ' . $name);
+      }
+    }
+  }
+
+  /**
+   * Runs a limited-range query on this database object.
+   *
+   * Use this as a substitute for ->query() when a subset of the query is to be
+   * returned. User-supplied arguments to the query should be passed in as
+   * separate parameters so that they can be properly escaped to avoid SQL
+   * injection attacks.
+   *
+   * @param $query
+   *   A string containing an SQL query.
+   * @param $args
+   *   An array of values to substitute into the query at placeholder markers.
+   * @param $from
+   *   The first result row to return.
+   * @param $count
+   *   The maximum number of result rows to return.
+   * @param $options
+   *   An array of options on the query.
+   *
+   * @return Drupal\Core\Database\StatementInterface
+   *   A database query result resource, or NULL if the query was not executed
+   *   correctly.
+   */
+  abstract public function queryRange($query, $from, $count, array $args = array(), array $options = array());
+
+  /**
+   * Generates a temporary table name.
+   *
+   * @return
+   *   A table name.
+   */
+  protected function generateTemporaryTableName() {
+    return "db_temporary_" . $this->temporaryNameIndex++;
+  }
+
+  /**
+   * Runs a SELECT query and stores its results in a temporary table.
+   *
+   * Use this as a substitute for ->query() when the results need to stored
+   * in a temporary table. Temporary tables exist for the duration of the page
+   * request. User-supplied arguments to the query should be passed in as
+   * separate parameters so that they can be properly escaped to avoid SQL
+   * injection attacks.
+   *
+   * Note that if you need to know how many results were returned, you should do
+   * a SELECT COUNT(*) on the temporary table afterwards.
+   *
+   * @param $query
+   *   A string containing a normal SELECT SQL query.
+   * @param $args
+   *   An array of values to substitute into the query at placeholder markers.
+   * @param $options
+   *   An associative array of options to control how the query is run. See
+   *   the documentation for DatabaseConnection::defaultOptions() for details.
+   *
+   * @return
+   *   The name of the temporary table.
+   */
+  abstract function queryTemporary($query, array $args = array(), array $options = array());
+
+  /**
+   * Returns the type of database driver.
+   *
+   * This is not necessarily the same as the type of the database itself. For
+   * instance, there could be two MySQL drivers, mysql and mysql_mock. This
+   * function would return different values for each, but both would return
+   * "mysql" for databaseType().
+   */
+  abstract public function driver();
+
+  /**
+   * Returns the version of the database server.
+   */
+  public function version() {
+    return $this->getAttribute(PDO::ATTR_SERVER_VERSION);
+  }
+
+  /**
+   * Determines if this driver supports transactions.
+   *
+   * @return
+   *   TRUE if this connection supports transactions, FALSE otherwise.
+   */
+  public function supportsTransactions() {
+    return $this->transactionSupport;
+  }
+
+  /**
+   * Determines if this driver supports transactional DDL.
+   *
+   * DDL queries are those that change the schema, such as ALTER queries.
+   *
+   * @return
+   *   TRUE if this connection supports transactions for DDL queries, FALSE
+   *   otherwise.
+   */
+  public function supportsTransactionalDDL() {
+    return $this->transactionalDDLSupport;
+  }
+
+  /**
+   * Returns the name of the PDO driver for this connection.
+   */
+  abstract public function databaseType();
+
+
+  /**
+   * Gets any special processing requirements for the condition operator.
+   *
+   * Some condition types require special processing, such as IN, because
+   * the value data they pass in is not a simple value. This is a simple
+   * overridable lookup function. Database connections should define only
+   * those operators they wish to be handled differently than the default.
+   *
+   * @param $operator
+   *   The condition operator, such as "IN", "BETWEEN", etc. Case-sensitive.
+   *
+   * @return
+   *   The extra handling directives for the specified operator, or NULL.
+   *
+   * @see Drupal\Core\Database\Query\Condition::compile()
+   */
+  abstract public function mapConditionOperator($operator);
+
+  /**
+   * Throws an exception to deny direct access to transaction commits.
+   *
+   * We do not want to allow users to commit transactions at any time, only
+   * by destroying the transaction object or allowing it to go out of scope.
+   * A direct commit bypasses all of the safety checks we've built on top of
+   * PDO's transaction routines.
+   *
+   * @throws Drupal\Core\Database\TransactionExplicitCommitNotAllowedException
+   *
+   * @see Drupal\Core\Database\Transaction
+   */
+  public function commit() {
+    throw new TransactionExplicitCommitNotAllowedException();
+  }
+
+  /**
+   * Retrieves an unique id from a given sequence.
+   *
+   * Use this function if for some reason you can't use a serial field. For
+   * example, MySQL has no ways of reading of the current value of a sequence
+   * and PostgreSQL can not advance the sequence to be larger than a given
+   * value. Or sometimes you just need a unique integer.
+   *
+   * @param $existing_id
+   *   After a database import, it might be that the sequences table is behind,
+   *   so by passing in the maximum existing id, it can be assured that we
+   *   never issue the same id.
+   *
+   * @return
+   *   An integer number larger than any number returned by earlier calls and
+   *   also larger than the $existing_id if one was passed in.
+   */
+  abstract public function nextId($existing_id = 0);
+}
diff --git a/core/lib/Drupal/Core/Database/ConnectionNotDefinedException.php b/core/lib/Drupal/Core/Database/ConnectionNotDefinedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..d14535822fe3c0f4a033612c428ecdf8285eab63
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/ConnectionNotDefinedException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\ConnectionNotDefinedException
+ */
+
+namespace Drupal\Core\Database;
+
+use RuntimeException;
+
+/**
+ * Exception thrown if an undefined database connection is requested.
+ */
+class ConnectionNotDefinedException extends RuntimeException {}
diff --git a/core/lib/Drupal/Core/Database/Database.php b/core/lib/Drupal/Core/Database/Database.php
new file mode 100644
index 0000000000000000000000000000000000000000..298c0115ab6a7699ba1eb687dc65238cedf71aa3
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Database.php
@@ -0,0 +1,431 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Database
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Primary front-controller for the database system.
+ *
+ * This class is uninstantiatable and un-extendable. It acts to encapsulate
+ * all control and shepherding of database connections into a single location
+ * without the use of globals.
+ */
+abstract class Database {
+
+  /**
+   * Flag to indicate a query call should simply return NULL.
+   *
+   * This is used for queries that have no reasonable return value anyway, such
+   * as INSERT statements to a table without a serial primary key.
+   */
+  const RETURN_NULL = 0;
+
+  /**
+   * Flag to indicate a query call should return the prepared statement.
+   */
+  const RETURN_STATEMENT = 1;
+
+  /**
+   * Flag to indicate a query call should return the number of affected rows.
+   */
+  const RETURN_AFFECTED = 2;
+
+  /**
+   * Flag to indicate a query call should return the "last insert id".
+   */
+  const RETURN_INSERT_ID = 3;
+
+  /**
+   * An nested array of all active connections. It is keyed by database name
+   * and target.
+   *
+   * @var array
+   */
+  static protected $connections = array();
+
+  /**
+   * A processed copy of the database connection information from settings.php.
+   *
+   * @var array
+   */
+  static protected $databaseInfo = NULL;
+
+  /**
+   * A list of key/target credentials to simply ignore.
+   *
+   * @var array
+   */
+  static protected $ignoreTargets = array();
+
+  /**
+   * The key of the currently active database connection.
+   *
+   * @var string
+   */
+  static protected $activeKey = 'default';
+
+  /**
+   * An array of active query log objects.
+   *
+   * Every connection has one and only one logger object for all targets and
+   * logging keys.
+   *
+   * array(
+   *   '$db_key' => DatabaseLog object.
+   * );
+   *
+   * @var array
+   */
+  static protected $logs = array();
+
+  /**
+   * Starts logging a given logging key on the specified connection.
+   *
+   * @param $logging_key
+   *   The logging key to log.
+   * @param $key
+   *   The database connection key for which we want to log.
+   *
+   * @return Drupal\Core\Database\Log
+   *   The query log object. Note that the log object does support richer
+   *   methods than the few exposed through the Database class, so in some
+   *   cases it may be desirable to access it directly.
+   *
+   * @see Drupal\Core\Database\Log
+   */
+  final public static function startLog($logging_key, $key = 'default') {
+    if (empty(self::$logs[$key])) {
+      self::$logs[$key] = new Log($key);
+
+      // Every target already active for this connection key needs to have the
+      // logging object associated with it.
+      if (!empty(self::$connections[$key])) {
+        foreach (self::$connections[$key] as $connection) {
+          $connection->setLogger(self::$logs[$key]);
+        }
+      }
+    }
+
+    self::$logs[$key]->start($logging_key);
+    return self::$logs[$key];
+  }
+
+  /**
+   * Retrieves the queries logged on for given logging key.
+   *
+   * This method also ends logging for the specified key. To get the query log
+   * to date without ending the logger request the logging object by starting
+   * it again (which does nothing to an open log key) and call methods on it as
+   * desired.
+   *
+   * @param $logging_key
+   *   The logging key to log.
+   * @param $key
+   *   The database connection key for which we want to log.
+   *
+   * @return array
+   *   The query log for the specified logging key and connection.
+   *
+   * @see Drupal\Core\Database\Log
+   */
+  final public static function getLog($logging_key, $key = 'default') {
+    if (empty(self::$logs[$key])) {
+      return NULL;
+    }
+    $queries = self::$logs[$key]->get($logging_key);
+    self::$logs[$key]->end($logging_key);
+    return $queries;
+  }
+
+  /**
+   * Gets the connection object for the specified database key and target.
+   *
+   * @param $target
+   *   The database target name.
+   * @param $key
+   *   The database connection key. Defaults to NULL which means the active key.
+   *
+   * @return Drupal\Core\Database\Connection
+   *   The corresponding connection object.
+   */
+  final public static function getConnection($target = 'default', $key = NULL) {
+    if (!isset($key)) {
+      // By default, we want the active connection, set in setActiveConnection.
+      $key = self::$activeKey;
+    }
+    // If the requested target does not exist, or if it is ignored, we fall back
+    // to the default target. The target is typically either "default" or
+    // "slave", indicating to use a slave SQL server if one is available. If
+    // it's not available, then the default/master server is the correct server
+    // to use.
+    if (!empty(self::$ignoreTargets[$key][$target]) || !isset(self::$databaseInfo[$key][$target])) {
+      $target = 'default';
+    }
+
+    if (!isset(self::$connections[$key][$target])) {
+      // If necessary, a new connection is opened.
+      self::$connections[$key][$target] = self::openConnection($key, $target);
+    }
+    return self::$connections[$key][$target];
+  }
+
+  /**
+   * Determines if there is an active connection.
+   *
+   * Note that this method will return FALSE if no connection has been
+   * established yet, even if one could be.
+   *
+   * @return
+   *   TRUE if there is at least one database connection established, FALSE
+   *   otherwise.
+   */
+  final public static function isActiveConnection() {
+    return !empty(self::$activeKey) && !empty(self::$connections) && !empty(self::$connections[self::$activeKey]);
+  }
+
+  /**
+   * Sets the active connection to the specified key.
+   *
+   * @return
+   *   The previous database connection key.
+   */
+  final public static function setActiveConnection($key = 'default') {
+    if (empty(self::$databaseInfo)) {
+      self::parseConnectionInfo();
+    }
+
+    if (!empty(self::$databaseInfo[$key])) {
+      $old_key = self::$activeKey;
+      self::$activeKey = $key;
+      return $old_key;
+    }
+  }
+
+  /**
+   * Process the configuration file for database information.
+   */
+  final public static function parseConnectionInfo() {
+    global $databases;
+
+    $database_info = is_array($databases) ? $databases : array();
+    foreach ($database_info as $index => $info) {
+      foreach ($database_info[$index] as $target => $value) {
+        // If there is no "driver" property, then we assume it's an array of
+        // possible connections for this target. Pick one at random. That allows
+        //  us to have, for example, multiple slave servers.
+        if (empty($value['driver'])) {
+          $database_info[$index][$target] = $database_info[$index][$target][mt_rand(0, count($database_info[$index][$target]) - 1)];
+        }
+
+        // Parse the prefix information.
+        if (!isset($database_info[$index][$target]['prefix'])) {
+          // Default to an empty prefix.
+          $database_info[$index][$target]['prefix'] = array(
+            'default' => '',
+          );
+        }
+        elseif (!is_array($database_info[$index][$target]['prefix'])) {
+          // Transform the flat form into an array form.
+          $database_info[$index][$target]['prefix'] = array(
+            'default' => $database_info[$index][$target]['prefix'],
+          );
+        }
+      }
+    }
+
+    if (!is_array(self::$databaseInfo)) {
+      self::$databaseInfo = $database_info;
+    }
+
+    // Merge the new $database_info into the existing.
+    // array_merge_recursive() cannot be used, as it would make multiple
+    // database, user, and password keys in the same database array.
+    else {
+      foreach ($database_info as $database_key => $database_values) {
+        foreach ($database_values as $target => $target_values) {
+          self::$databaseInfo[$database_key][$target] = $target_values;
+        }
+      }
+    }
+  }
+
+  /**
+   * Adds database connection information for a given key/target.
+   *
+   * This method allows the addition of new connection credentials at runtime.
+   * Under normal circumstances the preferred way to specify database
+   * credentials is via settings.php. However, this method allows them to be
+   * added at arbitrary times, such as during unit tests, when connecting to
+   * admin-defined third party databases, etc.
+   *
+   * If the given key/target pair already exists, this method will be ignored.
+   *
+   * @param $key
+   *   The database key.
+   * @param $target
+   *   The database target name.
+   * @param $info
+   *   The database connection information, as it would be defined in
+   *   settings.php. Note that the structure of this array will depend on the
+   *   database driver it is connecting to.
+   */
+  public static function addConnectionInfo($key, $target, $info) {
+    if (empty(self::$databaseInfo[$key][$target])) {
+      self::$databaseInfo[$key][$target] = $info;
+    }
+  }
+
+  /**
+   * Gets information on the specified database connection.
+   *
+   * @param $connection
+   *   The connection key for which we want information.
+   */
+  final public static function getConnectionInfo($key = 'default') {
+    if (empty(self::$databaseInfo)) {
+      self::parseConnectionInfo();
+    }
+
+    if (!empty(self::$databaseInfo[$key])) {
+      return self::$databaseInfo[$key];
+    }
+  }
+
+  /**
+   * Rename a connection and its corresponding connection information.
+   *
+   * @param $old_key
+   *   The old connection key.
+   * @param $new_key
+   *   The new connection key.
+   * @return
+   *   TRUE in case of success, FALSE otherwise.
+   */
+  final public static function renameConnection($old_key, $new_key) {
+    if (empty(self::$databaseInfo)) {
+      self::parseConnectionInfo();
+    }
+
+    if (!empty(self::$databaseInfo[$old_key]) && empty(self::$databaseInfo[$new_key])) {
+      // Migrate the database connection information.
+      self::$databaseInfo[$new_key] = self::$databaseInfo[$old_key];
+      unset(self::$databaseInfo[$old_key]);
+
+      // Migrate over the DatabaseConnection object if it exists.
+      if (isset(self::$connections[$old_key])) {
+        self::$connections[$new_key] = self::$connections[$old_key];
+        unset(self::$connections[$old_key]);
+      }
+
+      return TRUE;
+    }
+    else {
+      return FALSE;
+    }
+  }
+
+  /**
+   * Remove a connection and its corresponding connection information.
+   *
+   * @param $key
+   *   The connection key.
+   * @return
+   *   TRUE in case of success, FALSE otherwise.
+   */
+  final public static function removeConnection($key) {
+    if (isset(self::$databaseInfo[$key])) {
+      unset(self::$databaseInfo[$key]);
+      unset(self::$connections[$key]);
+      return TRUE;
+    }
+    else {
+      return FALSE;
+    }
+  }
+
+  /**
+   * Opens a connection to the server specified by the given key and target.
+   *
+   * @param $key
+   *   The database connection key, as specified in settings.php. The default is
+   *   "default".
+   * @param $target
+   *   The database target to open.
+   *
+   * @throws Drupal\Core\Database\ConnectionNotDefinedException
+   * @throws Drupal\Core\Database\DriverNotSpecifiedException
+   */
+  final protected static function openConnection($key, $target) {
+    if (empty(self::$databaseInfo)) {
+      self::parseConnectionInfo();
+    }
+
+    // If the requested database does not exist then it is an unrecoverable
+    // error.
+    if (!isset(self::$databaseInfo[$key])) {
+      throw new ConnectionNotDefinedException('The specified database connection is not defined: ' . $key);
+    }
+
+    if (!$driver = self::$databaseInfo[$key][$target]['driver']) {
+      throw new DriverNotSpecifiedException('Driver not specified for this database connection: ' . $key);
+    }
+
+    // We cannot rely on the registry yet, because the registry requires an
+    // open database connection.
+    $driver_class = "Drupal\\Core\\Database\\Driver\\{$driver}\\Connection";
+    $new_connection = new $driver_class(self::$databaseInfo[$key][$target]);
+    $new_connection->setTarget($target);
+    $new_connection->setKey($key);
+
+    // If we have any active logging objects for this connection key, we need
+    // to associate them with the connection we just opened.
+    if (!empty(self::$logs[$key])) {
+      $new_connection->setLogger(self::$logs[$key]);
+    }
+
+    return $new_connection;
+  }
+
+  /**
+   * Closes a connection to the server specified by the given key and target.
+   *
+   * @param $target
+   *   The database target name.  Defaults to NULL meaning that all target
+   *   connections will be closed.
+   * @param $key
+   *   The database connection key. Defaults to NULL which means the active key.
+   */
+  public static function closeConnection($target = NULL, $key = NULL) {
+    // Gets the active connection by default.
+    if (!isset($key)) {
+      $key = self::$activeKey;
+    }
+    // To close the connection, we need to unset the static variable.
+    if (isset($target)) {
+      unset(self::$connections[$key][$target]);
+    }
+    else {
+      unset(self::$connections[$key]);
+    }
+  }
+
+  /**
+   * Instructs the system to temporarily ignore a given key/target.
+   *
+   * At times we need to temporarily disable slave queries. To do so, call this
+   * method with the database key and the target to disable. That database key
+   * will then always fall back to 'default' for that key, even if it's defined.
+   *
+   * @param $key
+   *   The database connection key.
+   * @param $target
+   *   The target of the specified key to ignore.
+   */
+  public static function ignoreTarget($key, $target) {
+    self::$ignoreTargets[$key][$target] = TRUE;
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/DatabaseException.php b/core/lib/Drupal/Core/Database/DatabaseException.php
new file mode 100644
index 0000000000000000000000000000000000000000..019d656166664d5731f735e16f346a8a6c500b64
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/DatabaseException.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\DatabaseException
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Interface for a database exception.
+ *
+ * All Database exceptions should implement this interface so that they can be
+ * caught collectively.  Note that this applies only to Drupal-spawned
+ * exceptions.  PDOException will not implement this interface and module
+ * developers should account for it separately.
+ */
+interface DatabaseException { }
+
diff --git a/core/includes/database/mysql/database.inc b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
similarity index 95%
rename from core/includes/database/mysql/database.inc
rename to core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
index e024a7f396829a5a63e68deeeeae526ecf76725b..3b62fa703a09b99f94f8bf510ebea33cbe9bbfe8 100644
--- a/core/includes/database/mysql/database.inc
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
@@ -2,15 +2,24 @@
 
 /**
  * @file
- * Database interface code for MySQL database servers.
+ * Definition of Drupal\Core\Database\Driver\mysql\Connection
  */
 
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\TransactionCommitFailedException;
+use Drupal\Core\Database\Connection as DatabaseConnection;
+
+use PDO;
+use PDOException;
+
 /**
  * @ingroup database
  * @{
  */
 
-class DatabaseConnection_mysql extends DatabaseConnection {
+class Connection extends DatabaseConnection {
 
   /**
    * Flag to indicate if we have registered the nextID cleanup function.
@@ -165,7 +174,7 @@ protected function popCommittableTransactions() {
       unset($this->transactionLayers[$name]);
       if (empty($this->transactionLayers)) {
         if (!PDO::commit()) {
-          throw new DatabaseTransactionCommitFailedException();
+          throw new TransactionCommitFailedException();
         }
       }
       else {
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Delete.php b/core/lib/Drupal/Core/Database/Driver/mysql/Delete.php
new file mode 100644
index 0000000000000000000000000000000000000000..de0db11ae586767b302769eba5969d5094baffb7
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Delete.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\mysql\Delete
+ */
+
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Query\Delete as QueryDelete;
+
+class Delete extends QueryDelete { }
diff --git a/core/includes/database/mysql/query.inc b/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php
similarity index 76%
rename from core/includes/database/mysql/query.inc
rename to core/lib/Drupal/Core/Database/Driver/mysql/Insert.php
index 888b6a5a450e613b172814e53b0f53f27e76cf69..233118c5aa28931d3ba351502d492f58b7ac701b 100644
--- a/core/includes/database/mysql/query.inc
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php
@@ -1,17 +1,15 @@
 <?php
 
-/**
- * @ingroup database
- * @{
- */
-
 /**
  * @file
- * Query code for MySQL embedded database engine.
+ * Definition of Drupal\Core\Database\Driver\mysql\Insert
  */
 
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Query\Insert as QueryInsert;
 
-class InsertQuery_mysql extends InsertQuery {
+class Insert extends QueryInsert {
 
   public function execute() {
     if (!$this->preExecute()) {
@@ -85,23 +83,3 @@ public function __toString() {
     return $query;
   }
 }
-
-class TruncateQuery_mysql extends TruncateQuery {
-  public function __toString() {
-    // TRUNCATE is actually a DDL statement on MySQL, and DDL statements are
-    // not transactional, and result in an implicit COMMIT. When we are in a
-    // transaction, fallback to the slower, but transactional, DELETE.
-    if ($this->connection->inTransaction()) {
-      // Create a comment string to prepend to the query.
-      $comments = $this->connection->makeComment($this->comments);
-      return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '}';
-    }
-    else {
-      return parent::__toString();
-    }
-  }
-}
-
-/**
- * @} End of "ingroup database".
- */
diff --git a/core/includes/database/mysql/install.inc b/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php
similarity index 71%
rename from core/includes/database/mysql/install.inc
rename to core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php
index 75f2ae390504361204acf9bc9c8c4ceb476327b4..4835103de489adca72df34830f525ada49a1da11 100644
--- a/core/includes/database/mysql/install.inc
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php
@@ -2,13 +2,17 @@
 
 /**
  * @file
- * Installation code for MySQL embedded database engine.
+ * Definition of Drupal\Core\Database\Driver\mysql\Install\Tasks
  */
 
+namespace Drupal\Core\Database\Driver\mysql\Install;
+
+use Drupal\Core\Database\Install\Tasks as InstallTasks;
+
 /**
  * Specifies installation tasks for MySQL and equivalent databases.
  */
-class DatabaseTasks_mysql extends DatabaseTasks {
+class Tasks extends InstallTasks {
   /**
    * The PDO driver name for MySQL and equivalent databases.
    *
@@ -30,4 +34,3 @@ public function minimumVersion() {
     return '5.0.15';
   }
 }
-
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Merge.php b/core/lib/Drupal/Core/Database/Driver/mysql/Merge.php
new file mode 100644
index 0000000000000000000000000000000000000000..c48b830a566592a6bc4f5e2898a13d18630d5616
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Merge.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\mysql\Merge
+ */
+
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Query\Merge as QueryMerge;
+
+class Merge extends QueryMerge { }
diff --git a/core/includes/database/mysql/schema.inc b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
similarity index 85%
rename from core/includes/database/mysql/schema.inc
rename to core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
index 4e88fa169ebeb6dca90fdf66a55f6ffe10f3bc06..24c3b4a6b11ac9125df1e8c1dab57df603773b41 100644
--- a/core/includes/database/mysql/schema.inc
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
@@ -2,16 +2,25 @@
 
 /**
  * @file
- * Database schema code for MySQL database servers.
+ * Definition of Drupal\Core\Database\Driver\mysql\Schema
  */
 
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\SchemaObjectExistsException;
+use Drupal\Core\Database\SchemaObjectDoesNotExistException;
+use Drupal\Core\Database\Schema as DatabaseSchema;
+
+use Exception;
 
 /**
  * @ingroup schemaapi
  * @{
  */
 
-class DatabaseSchema_mysql extends DatabaseSchema {
+class Schema extends DatabaseSchema {
 
   /**
    * Maximum length of a table comment in MySQL.
@@ -59,7 +68,7 @@ protected function buildTableNameCondition($table_name, $operator = '=', $add_pr
 
     $table_info = $this->getPrefixInfo($table_name, $add_prefix);
 
-    $condition = new DatabaseCondition('AND');
+    $condition = new Condition('AND');
     $condition->condition('table_schema', $table_info['database']);
     $condition->condition('table_name', $table_info['table'], $operator);
     return $condition;
@@ -296,10 +305,10 @@ protected function createKeysSqlHelper($fields) {
 
   public function renameTable($table, $new_name) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename %table to %table_new: table %table doesn't exist.", array('%table' => $table, '%table_new' => $new_name)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot rename %table to %table_new: table %table doesn't exist.", array('%table' => $table, '%table_new' => $new_name)));
     }
     if ($this->tableExists($new_name)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot rename %table to %table_new: table %table_new already exists.", array('%table' => $table, '%table_new' => $new_name)));
+      throw new SchemaObjectExistsException(t("Cannot rename %table to %table_new: table %table_new already exists.", array('%table' => $table, '%table_new' => $new_name)));
     }
 
     $info = $this->getPrefixInfo($new_name);
@@ -317,10 +326,10 @@ public function dropTable($table) {
 
   public function addField($table, $field, $spec, $keys_new = array()) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
     }
     if ($this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
+      throw new SchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
     }
 
     $fixnull = FALSE;
@@ -356,7 +365,7 @@ public function dropField($table, $field) {
 
   public function fieldSetDefault($table, $field, $default) {
     if (!$this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
     if (!isset($default)) {
@@ -371,7 +380,7 @@ public function fieldSetDefault($table, $field, $default) {
 
   public function fieldSetNoDefault($table, $field) {
     if (!$this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
     $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN `' . $field . '` DROP DEFAULT');
@@ -386,10 +395,10 @@ public function indexExists($table, $name) {
 
   public function addPrimaryKey($table, $fields) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add primary key to table %table: table doesn't exist.", array('%table' => $table)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add primary key to table %table: table doesn't exist.", array('%table' => $table)));
     }
     if ($this->indexExists($table, 'PRIMARY')) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
+      throw new SchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
     }
 
     $this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . $this->createKeySql($fields) . ')');
@@ -406,10 +415,10 @@ public function dropPrimaryKey($table) {
 
   public function addUniqueKey($table, $name, $fields) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add unique key %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add unique key %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
     }
     if ($this->indexExists($table, $name)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
     }
 
     $this->connection->query('ALTER TABLE {' . $table . '} ADD UNIQUE KEY `' . $name . '` (' . $this->createKeySql($fields) . ')');
@@ -426,10 +435,10 @@ public function dropUniqueKey($table, $name) {
 
   public function addIndex($table, $name, $fields) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add index %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add index %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
     }
     if ($this->indexExists($table, $name)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
     }
 
     $this->connection->query('ALTER TABLE {' . $table . '} ADD INDEX `' . $name . '` (' . $this->createKeySql($fields) . ')');
@@ -446,10 +455,10 @@ public function dropIndex($table, $name) {
 
   public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
     if (!$this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot change the definition of field %table.%name: field doesn't exist.", array('%table' => $table, '%name' => $field)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot change the definition of field %table.%name: field doesn't exist.", array('%table' => $table, '%name' => $field)));
     }
     if (($field != $field_new) && $this->fieldExists($table, $field_new)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot rename field %table.%name to %name_new: target field already exists.", array('%table' => $table, '%name' => $field, '%name_new' => $field_new)));
+      throw new SchemaObjectExistsException(t("Cannot rename field %table.%name to %name_new: target field already exists.", array('%table' => $table, '%name' => $field, '%name_new' => $field_new)));
     }
 
     $sql = 'ALTER TABLE {' . $table . '} CHANGE `' . $field . '` ' . $this->createFieldSql($field_new, $this->processField($spec));
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Select.php b/core/lib/Drupal/Core/Database/Driver/mysql/Select.php
new file mode 100644
index 0000000000000000000000000000000000000000..aecae55a2fbaa017be7289c1c328af52c1c3a0aa
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Select.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\mysql\Select
+ */
+
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Query\Select as QuerySelect;
+
+class Select extends QuerySelect { }
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Transaction.php b/core/lib/Drupal/Core/Database/Driver/mysql/Transaction.php
new file mode 100644
index 0000000000000000000000000000000000000000..570a1300f3b0a9ef096124b488eedcdda0e70f9f
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Transaction.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\mysql\Transaction
+ */
+
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Transaction as DatabaseTransaction;
+
+class Transaction extends DatabaseTransaction { }
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Truncate.php b/core/lib/Drupal/Core/Database/Driver/mysql/Truncate.php
new file mode 100644
index 0000000000000000000000000000000000000000..d0adfad10f2b4f26dcb17fc96ef3d87fe784b3da
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Truncate.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\mysql\Truncate
+ */
+
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Query\Truncate as QueryTruncate;
+
+class Truncate extends QueryTruncate {
+  public function __toString() {
+    // TRUNCATE is actually a DDL statement on MySQL, and DDL statements are
+    // not transactional, and result in an implicit COMMIT. When we are in a
+    // transaction, fallback to the slower, but transactional, DELETE.
+    if ($this->connection->inTransaction()) {
+      // Create a comment string to prepend to the query.
+      $comments = $this->connection->makeComment($this->comments);
+      return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '}';
+    }
+    else {
+      return parent::__toString();
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Update.php b/core/lib/Drupal/Core/Database/Driver/mysql/Update.php
new file mode 100644
index 0000000000000000000000000000000000000000..5b3bda68b74e3d46c5050d4c2e4412b5a2e037ae
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Update.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\mysql\Update
+ */
+
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Query\Update as QueryUpdate;
+
+class Update extends QueryUpdate { }
diff --git a/core/includes/database/pgsql/database.inc b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
similarity index 89%
rename from core/includes/database/pgsql/database.inc
rename to core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
index 68300e55368e4bfd742e397f8fa3311df4bc19fb..6903a141991d02d143e89f6589a60c73ed8ea731 100644
--- a/core/includes/database/pgsql/database.inc
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
@@ -2,20 +2,29 @@
 
 /**
  * @file
- * Database interface code for PostgreSQL database servers.
+ * Definition of Drupal\Core\Database\Driver\pgsql\Connection
  */
 
+namespace Drupal\Core\Database\Driver\pgsql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection as DatabaseConnection;
+use Drupal\Core\Database\StatementInterface;
+
+use PDO;
+use PDOException;
+
 /**
  * @ingroup database
  * @{
  */
 
-/**
- * The name by which to obtain a lock for retrive the next insert id.
- */
-const POSTGRESQL_NEXTID_LOCK = 1000;
+class Connection extends DatabaseConnection {
 
-class DatabaseConnection_pgsql extends DatabaseConnection {
+  /**
+   * The name by which to obtain a lock for retrive the next insert id.
+   */
+  const POSTGRESQL_NEXTID_LOCK = 1000;
 
   public function __construct(array $connection_options = array()) {
     // This driver defaults to transaction support, except if explicitly passed FALSE.
@@ -92,7 +101,7 @@ public function query($query, array $args = array(), $options = array()) {
     }
 
     try {
-      if ($query instanceof DatabaseStatementInterface) {
+      if ($query instanceof StatementInterface) {
         $stmt = $query;
         $stmt->execute(NULL, $options);
       }
@@ -118,7 +127,7 @@ public function query($query, array $args = array(), $options = array()) {
     catch (PDOException $e) {
       if ($options['throw_exception']) {
         // Add additional debug information.
-        if ($query instanceof DatabaseStatementInterface) {
+        if ($query instanceof StatementInterface) {
           $e->query_string = $stmt->getQueryString();
         }
         else {
@@ -187,13 +196,13 @@ public function nextId($existing = 0) {
     // PostgreSQL advisory locks are simply locks to be used by an
     // application such as Drupal. This will prevent other Drupal proccesses
     // from altering the sequence while we are.
-    $this->query("SELECT pg_advisory_lock(" . POSTGRESQL_NEXTID_LOCK . ")");
+    $this->query("SELECT pg_advisory_lock(" . self::POSTGRESQL_NEXTID_LOCK . ")");
 
     // While waiting to obtain the lock, the sequence may have been altered
     // so lets try again to obtain an adequate value.
     $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
     if ($id > $existing) {
-      $this->query("SELECT pg_advisory_unlock(" . POSTGRESQL_NEXTID_LOCK . ")");
+      $this->query("SELECT pg_advisory_unlock(" . self::POSTGRESQL_NEXTID_LOCK . ")");
       return $id;
     }
 
@@ -203,7 +212,7 @@ public function nextId($existing = 0) {
     // Retrive the next id. We know this will be as high as we want it.
     $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
 
-    $this->query("SELECT pg_advisory_unlock(" . POSTGRESQL_NEXTID_LOCK . ")");
+    $this->query("SELECT pg_advisory_unlock(" . self::POSTGRESQL_NEXTID_LOCK . ")");
 
     return $id;
   }
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9914ca97d9b94a6105368bb13f48f709d4838f0
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\pgsql\Delete
+ */
+
+namespace Drupal\Core\Database\Driver\pgsql;
+
+use Drupal\Core\Database\Query\Delete as QueryDelete;
+
+class Delete extends QueryDelete { }
diff --git a/core/includes/database/pgsql/query.inc b/core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php
similarity index 71%
rename from core/includes/database/pgsql/query.inc
rename to core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php
index f3783a9ca8f9ceb4f745c650fa826ee3271e1df4..dffa1fdcbacd8d24a0039adca0372d7b2a092b86 100644
--- a/core/includes/database/pgsql/query.inc
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php
@@ -1,17 +1,23 @@
 <?php
 
 /**
- * @ingroup database
- * @{
+ * @file
+ * Definition of Drupal\Core\Database\Driver\pgsql\Insert
  */
 
+namespace Drupal\Core\Database\Driver\pgsql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Query\Insert as QueryInsert;
+
+use PDO;
+
 /**
- * @file
- * Query code for PostgreSQL embedded database engine.
+ * @ingroup database
+ * @{
  */
 
-
-class InsertQuery_pgsql extends InsertQuery {
+class Insert extends QueryInsert {
 
   public function execute() {
     if (!$this->preExecute()) {
@@ -146,64 +152,3 @@ public function __toString() {
     return $query;
   }
 }
-
-class UpdateQuery_pgsql extends UpdateQuery {
-  public function execute() {
-    $max_placeholder = 0;
-    $blobs = array();
-    $blob_count = 0;
-
-    // Because we filter $fields the same way here and in __toString(), the
-    // placeholders will all match up properly.
-    $stmt = $this->connection->prepareQuery((string) $this);
-
-    // Fetch the list of blobs and sequences used on that table.
-    $table_information = $this->connection->schema()->queryTableInformation($this->table);
-
-    // Expressions take priority over literal fields, so we process those first
-    // and remove any literal fields that conflict.
-    $fields = $this->fields;
-    $expression_fields = array();
-    foreach ($this->expressionFields as $field => $data) {
-      if (!empty($data['arguments'])) {
-        foreach ($data['arguments'] as $placeholder => $argument) {
-          // We assume that an expression will never happen on a BLOB field,
-          // which is a fairly safe assumption to make since in most cases
-          // it would be an invalid query anyway.
-          $stmt->bindParam($placeholder, $data['arguments'][$placeholder]);
-        }
-      }
-      unset($fields[$field]);
-    }
-
-    foreach ($fields as $field => $value) {
-      $placeholder = ':db_update_placeholder_' . ($max_placeholder++);
-
-      if (isset($table_information->blob_fields[$field])) {
-        $blobs[$blob_count] = fopen('php://memory', 'a');
-        fwrite($blobs[$blob_count], $value);
-        rewind($blobs[$blob_count]);
-        $stmt->bindParam($placeholder, $blobs[$blob_count], PDO::PARAM_LOB);
-        ++$blob_count;
-      }
-      else {
-        $stmt->bindParam($placeholder, $fields[$field]);
-      }
-    }
-
-    if (count($this->condition)) {
-      $this->condition->compile($this->connection, $this);
-
-      $arguments = $this->condition->arguments();
-      foreach ($arguments as $placeholder => $value) {
-        $stmt->bindParam($placeholder, $arguments[$placeholder]);
-      }
-    }
-
-    $options = $this->queryOptions;
-    $options['already_prepared'] = TRUE;
-    $this->connection->query($stmt, $options);
-
-    return $stmt->rowCount();
-  }
-}
diff --git a/core/includes/database/pgsql/install.inc b/core/lib/Drupal/Core/Database/Driver/pgsql/Install/Tasks.php
similarity index 95%
rename from core/includes/database/pgsql/install.inc
rename to core/lib/Drupal/Core/Database/Driver/pgsql/Install/Tasks.php
index c350634ec40058a19c7ae470f2d5c8a03bc71c4c..c3ddffb4b78a31e5cec9c6a997d675ae8ccd20d5 100644
--- a/core/includes/database/pgsql/install.inc
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Install/Tasks.php
@@ -2,13 +2,17 @@
 
 /**
  * @file
- * Install functions for PostgreSQL embedded database engine.
+ * Definition of Drupal\Core\Database\Driver\pgsql\Install\Tasks
  */
 
+namespace Drupal\Core\Database\Driver\pgsql\Install;
 
-// PostgreSQL specific install functions
+use Drupal\Core\Database\Install\Tasks as InstallTasks;
 
-class DatabaseTasks_pgsql extends DatabaseTasks {
+/**
+ * PostgreSQL specific install functions
+ */
+class Tasks extends InstallTasks {
   protected $pdoDriver = 'pgsql';
 
   public function __construct() {
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Merge.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Merge.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3a2ae0938b837400df9f3e123ea9aa5a12f3593
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Merge.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\pgsql\Merge
+ */
+
+namespace Drupal\Core\Database\Driver\pgsql;
+
+use Drupal\Core\Database\Query\Merge as QueryMerge;
+
+class Merge extends QueryMerge { }
diff --git a/core/includes/database/pgsql/schema.inc b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
similarity index 88%
rename from core/includes/database/pgsql/schema.inc
rename to core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
index 49adbf9077627e33fa354b7521cd642c4db9c8ef..7206e178dba0a37da6b061eb94064c6e84d79484 100644
--- a/core/includes/database/pgsql/schema.inc
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -2,15 +2,25 @@
 
 /**
  * @file
- * Database schema code for PostgreSQL database servers.
+ * Definition of Drupal\Core\Database\Driver\pgsql\Schema
  */
 
+namespace Drupal\Core\Database\Driver\pgsql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\SchemaObjectExistsException;
+use Drupal\Core\Database\SchemaObjectDoesNotExistException;
+use Drupal\Core\Database\Schema as DatabaseSchema;
+
+use Exception;
+
 /**
  * @ingroup schemaapi
  * @{
  */
 
-class DatabaseSchema_pgsql extends DatabaseSchema {
+class Schema extends DatabaseSchema {
 
   /**
    * A cache of information about blob columns and sequences of tables.
@@ -314,10 +324,10 @@ protected function _createKeySql($fields) {
 
   function renameTable($table, $new_name) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename %table to %table_new: table %table doesn't exist.", array('%table' => $table, '%table_new' => $new_name)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot rename %table to %table_new: table %table doesn't exist.", array('%table' => $table, '%table_new' => $new_name)));
     }
     if ($this->tableExists($new_name)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot rename %table to %table_new: table %table_new already exists.", array('%table' => $table, '%table_new' => $new_name)));
+      throw new SchemaObjectExistsException(t("Cannot rename %table to %table_new: table %table_new already exists.", array('%table' => $table, '%table_new' => $new_name)));
     }
 
     // Get the schema and tablename for the old table.
@@ -351,10 +361,10 @@ public function dropTable($table) {
 
   public function addField($table, $field, $spec, $new_keys = array()) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
     }
     if ($this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
+      throw new SchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
     }
 
     $fixnull = FALSE;
@@ -393,7 +403,7 @@ public function dropField($table, $field) {
 
   public function fieldSetDefault($table, $field, $default) {
     if (!$this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
     if (!isset($default)) {
@@ -408,7 +418,7 @@ public function fieldSetDefault($table, $field, $default) {
 
   public function fieldSetNoDefault($table, $field) {
     if (!$this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
     $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" DROP DEFAULT');
@@ -435,10 +445,10 @@ protected function constraintExists($table, $name) {
 
   public function addPrimaryKey($table, $fields) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add primary key to table %table: table doesn't exist.", array('%table' => $table)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add primary key to table %table: table doesn't exist.", array('%table' => $table)));
     }
     if ($this->constraintExists($table, 'pkey')) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
+      throw new SchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
     }
 
     $this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . implode(',', $fields) . ')');
@@ -455,10 +465,10 @@ public function dropPrimaryKey($table) {
 
   function addUniqueKey($table, $name, $fields) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add unique key %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add unique key %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
     }
     if ($this->constraintExists($table, $name . '_key')) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
     }
 
     $this->connection->query('ALTER TABLE {' . $table . '} ADD CONSTRAINT "' . $this->prefixNonTable($table, $name, 'key') . '" UNIQUE (' . implode(',', $fields) . ')');
@@ -475,10 +485,10 @@ public function dropUniqueKey($table, $name) {
 
   public function addIndex($table, $name, $fields) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add index %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add index %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
     }
     if ($this->indexExists($table, $name)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
     }
 
     $this->connection->query($this->_createIndexSql($table, $name, $fields));
@@ -495,10 +505,10 @@ public function dropIndex($table, $name) {
 
   public function changeField($table, $field, $field_new, $spec, $new_keys = array()) {
     if (!$this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot change the definition of field %table.%name: field doesn't exist.", array('%table' => $table, '%name' => $field)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot change the definition of field %table.%name: field doesn't exist.", array('%table' => $table, '%name' => $field)));
     }
     if (($field != $field_new) && $this->fieldExists($table, $field_new)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot rename field %table.%name to %name_new: target field already exists.", array('%table' => $table, '%name' => $field, '%name_new' => $field_new)));
+      throw new SchemaObjectExistsException(t("Cannot rename field %table.%name to %name_new: target field already exists.", array('%table' => $table, '%name' => $field, '%name_new' => $field_new)));
     }
 
     $spec = $this->processField($spec);
@@ -615,3 +625,7 @@ public function getComment($table, $column = NULL) {
     }
   }
 }
+
+/**
+ * @} End of "ingroup database".
+ */
diff --git a/core/includes/database/pgsql/select.inc b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
similarity index 94%
rename from core/includes/database/pgsql/select.inc
rename to core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
index d1d83828118d9bbbd3de7cfedd506a8b862fedd8..a9226b26dbcfb7416546685c221c402e9a297a39 100644
--- a/core/includes/database/pgsql/select.inc
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
@@ -2,15 +2,19 @@
 
 /**
  * @file
- * Select builder for PostgreSQL database engine.
+ * Definition of Drupal\Core\Database\Driver\pgsql\Select
  */
 
+namespace Drupal\Core\Database\Driver\pgsql;
+
+use Drupal\Core\Database\Query\Select as QuerySelect;
+
 /**
  * @ingroup database
  * @{
  */
 
-class SelectQuery_pgsql extends SelectQuery {
+class Select extends QuerySelect {
 
   public function orderRandom() {
     $alias = $this->addExpression('RANDOM()', 'random_field');
@@ -105,4 +109,3 @@ public function orderBy($field, $direction = 'ASC') {
 /**
  * @} End of "ingroup database".
  */
-
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Transaction.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Transaction.php
new file mode 100644
index 0000000000000000000000000000000000000000..028672243569869a610df096e9d0a7b6da1a1f15
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Transaction.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\pgsql\Transaction
+ */
+
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Transaction as DatabaseTransaction;
+
+class Transaction extends DatabaseTransaction { }
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Truncate.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Truncate.php
new file mode 100644
index 0000000000000000000000000000000000000000..e2fa83dac7c40f2ec6de932847de8301e78ab3fd
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Truncate.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\pgsql\Truncate
+ */
+
+namespace Drupal\Core\Database\Driver\pgsql;
+
+use Drupal\Core\Database\Query\Truncate as QueryTruncate;
+
+class Truncate extends QueryTruncate { }
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php
new file mode 100644
index 0000000000000000000000000000000000000000..de738bfda996cf0a1db53f8e2e99d7e8488ecdc1
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\pgsql\Update
+ */
+
+namespace Drupal\Core\Database\Driver\pgsql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Query\Update as QueryUpdate;
+
+use PDO;
+
+class Update extends QueryUpdate {
+
+  public function execute() {
+    $max_placeholder = 0;
+    $blobs = array();
+    $blob_count = 0;
+
+    // Because we filter $fields the same way here and in __toString(), the
+    // placeholders will all match up properly.
+    $stmt = $this->connection->prepareQuery((string) $this);
+
+    // Fetch the list of blobs and sequences used on that table.
+    $table_information = $this->connection->schema()->queryTableInformation($this->table);
+
+    // Expressions take priority over literal fields, so we process those first
+    // and remove any literal fields that conflict.
+    $fields = $this->fields;
+    $expression_fields = array();
+    foreach ($this->expressionFields as $field => $data) {
+      if (!empty($data['arguments'])) {
+        foreach ($data['arguments'] as $placeholder => $argument) {
+          // We assume that an expression will never happen on a BLOB field,
+          // which is a fairly safe assumption to make since in most cases
+          // it would be an invalid query anyway.
+          $stmt->bindParam($placeholder, $data['arguments'][$placeholder]);
+        }
+      }
+      unset($fields[$field]);
+    }
+
+    foreach ($fields as $field => $value) {
+      $placeholder = ':db_update_placeholder_' . ($max_placeholder++);
+
+      if (isset($table_information->blob_fields[$field])) {
+        $blobs[$blob_count] = fopen('php://memory', 'a');
+        fwrite($blobs[$blob_count], $value);
+        rewind($blobs[$blob_count]);
+        $stmt->bindParam($placeholder, $blobs[$blob_count], PDO::PARAM_LOB);
+        ++$blob_count;
+      }
+      else {
+        $stmt->bindParam($placeholder, $fields[$field]);
+      }
+    }
+
+    if (count($this->condition)) {
+      $this->condition->compile($this->connection, $this);
+
+      $arguments = $this->condition->arguments();
+      foreach ($arguments as $placeholder => $value) {
+        $stmt->bindParam($placeholder, $arguments[$placeholder]);
+      }
+    }
+
+    $options = $this->queryOptions;
+    $options['already_prepared'] = TRUE;
+    $this->connection->query($stmt, $options);
+
+    return $stmt->rowCount();
+  }
+}
diff --git a/core/includes/database/sqlite/database.inc b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
similarity index 67%
rename from core/includes/database/sqlite/database.inc
rename to core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
index 5de219e8d79841d5a359316542645d5f0fffa28a..1587a632dd0812e27e694a503ae9956ffaff3cd4 100644
--- a/core/includes/database/sqlite/database.inc
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
@@ -2,20 +2,25 @@
 
 /**
  * @file
- * Database interface code for SQLite embedded database engine.
+ * Definition of Drupal\Core\Database\Driver\sqlite\Connection
  */
 
-/**
- * @ingroup database
- * @{
- */
+namespace Drupal\Core\Database\Driver\sqlite;
 
-include_once DRUPAL_ROOT . '/core/includes/database/prefetch.inc';
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\TransactionNoActiveException;
+use Drupal\Core\Database\TransactionNameNonUniqueException;
+use Drupal\Core\Database\TransactionCommitFailedException;
+use Drupal\Core\Database\Driver\sqlite\Statement;
+use Drupal\Core\Database\Connection as DatabaseConnection;
+
+use PDO;
+use Exception;
 
 /**
  * Specific SQLite implementation of DatabaseConnection.
  */
-class DatabaseConnection_sqlite extends DatabaseConnection {
+class Connection extends DatabaseConnection {
 
   /**
    * Whether this database connection supports savepoints.
@@ -37,7 +42,7 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
   /**
    * All databases attached to the current database. This is used to allow
    * prefixes to be safely handled without locking the table
-   * 
+   *
    * @var array
    */
   protected $attachedDatabases = array();
@@ -46,10 +51,10 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
    * Whether or not a table has been dropped this request: the destructor will
    * only try to get rid of unnecessary databases if there is potential of them
    * being empty.
-   * 
-   * This variable is set to public because DatabaseSchema_sqlite needs to
+   *
+   * This variable is set to public because Schema needs to
    * access it. However, it should not be manually set.
-   * 
+   *
    * @var boolean
    */
   var $tableDropped = FALSE;
@@ -217,11 +222,11 @@ public function sqlFunctionRand($seed = NULL) {
    * SQLite-specific implementation of DatabaseConnection::prepare().
    *
    * We don't use prepared statements at all at this stage. We just create
-   * a DatabaseStatement_sqlite object, that will create a PDOStatement
+   * a Statement object, that will create a PDOStatement
    * using the semi-private PDOPrepare() method below.
    */
   public function prepare($query, $options = array()) {
-    return new DatabaseStatement_sqlite($this, $query, $options);
+    return new Statement($this, $query, $options);
   }
 
   /**
@@ -232,9 +237,9 @@ public function prepare($query, $options = array()) {
    * destructor is called and SQLite does not allow data change (INSERT,
    * UPDATE etc) on a table which has open SELECT statements, you should never
    * call this function and keep a PDOStatement object alive as that can lead
-   * to a deadlock. This really, really should be private, but as
-   * DatabaseStatement_sqlite needs to call it, we have no other choice but to
-   * expose this function to the world.
+   * to a deadlock. This really, really should be private, but as Statement
+   * needs to call it, we have no other choice but to expose this function to
+   * the world.
    */
   public function PDOPrepare($query, array $options = array()) {
     return parent::prepare($query, $options);
@@ -304,7 +309,7 @@ public function rollback($savepoint_name = 'drupal_transaction') {
     }
 
     if (!$this->inTransaction()) {
-      throw new DatabaseTransactionNoActiveException();
+      throw new TransactionNoActiveException();
     }
     // A previous rollback to an earlier savepoint may mean that the savepoint
     // in question has already been rolled back.
@@ -340,7 +345,7 @@ public function pushTransaction($name) {
       return;
     }
     if (isset($this->transactionLayers[$name])) {
-      throw new DatabaseTransactionNameNonUniqueException($name . " is already in use.");
+      throw new TransactionNameNonUniqueException($name . " is already in use.");
     }
     if (!$this->inTransaction()) {
       PDO::beginTransaction();
@@ -356,7 +361,7 @@ public function popTransaction($name) {
       return;
     }
     if (!$this->inTransaction()) {
-      throw new DatabaseTransactionNoActiveException();
+      throw new TransactionNoActiveException();
     }
 
     // Commit everything since SAVEPOINT $name.
@@ -371,7 +376,7 @@ public function popTransaction($name) {
           PDO::rollBack();
         }
         elseif (!PDO::commit()) {
-          throw new DatabaseTransactionCommitFailedException();
+          throw new TransactionCommitFailedException();
         }
       }
       else {
@@ -381,141 +386,3 @@ public function popTransaction($name) {
   }
 
 }
-
-/**
- * Specific SQLite implementation of DatabaseConnection.
- *
- * See DatabaseConnection_sqlite::PDOPrepare() for reasons why we must prefetch
- * the data instead of using PDOStatement.
- *
- * @see DatabaseConnection_sqlite::PDOPrepare()
- */
-class DatabaseStatement_sqlite extends DatabaseStatementPrefetch implements Iterator, DatabaseStatementInterface {
-
-  /**
-   * SQLite specific implementation of getStatement().
-   *
-   * The PDO SQLite layer doesn't replace numeric placeholders in queries
-   * correctly, and this makes numeric expressions (such as COUNT(*) >= :count)
-   * fail. We replace numeric placeholders in the query ourselves to work
-   * around this bug.
-   *
-   * See http://bugs.php.net/bug.php?id=45259 for more details.
-   */
-  protected function getStatement($query, &$args = array()) {
-    if (count($args)) {
-      // Check if $args is a simple numeric array.
-      if (range(0, count($args) - 1) === array_keys($args)) {
-        // In that case, we have unnamed placeholders.
-        $count = 0;
-        $new_args = array();
-        foreach ($args as $value) {
-          if (is_float($value) || is_int($value)) {
-            if (is_float($value)) {
-              // Force the conversion to float so as not to loose precision
-              // in the automatic cast.
-              $value = sprintf('%F', $value);
-            }
-            $query = substr_replace($query, $value, strpos($query, '?'), 1);
-          }
-          else {
-            $placeholder = ':db_statement_placeholder_' . $count++;
-            $query = substr_replace($query, $placeholder, strpos($query, '?'), 1);
-            $new_args[$placeholder] = $value;
-          }
-        }
-        $args = $new_args;
-      }
-      else {
-        // Else, this is using named placeholders.
-        foreach ($args as $placeholder => $value) {
-          if (is_float($value) || is_int($value)) {
-            if (is_float($value)) {
-              // Force the conversion to float so as not to loose precision
-              // in the automatic cast.
-              $value = sprintf('%F', $value);
-            }
-
-            // We will remove this placeholder from the query as PDO throws an
-            // exception if the number of placeholders in the query and the
-            // arguments does not match.
-            unset($args[$placeholder]);
-            // PDO allows placeholders to not be prefixed by a colon. See
-            // http://marc.info/?l=php-internals&m=111234321827149&w=2 for
-            // more.
-            if ($placeholder[0] != ':') {
-              $placeholder = ":$placeholder";
-            }
-            // When replacing the placeholders, make sure we search for the
-            // exact placeholder. For example, if searching for
-            // ':db_placeholder_1', do not replace ':db_placeholder_11'.
-            $query = preg_replace('/' . preg_quote($placeholder) . '\b/', $value, $query);
-          }
-        }
-      }
-    }
-
-    return $this->dbh->PDOPrepare($query);
-  }
-
-  public function execute($args = array(), $options = array()) {
-    try {
-      $return = parent::execute($args, $options);
-    }
-    catch (PDOException $e) {
-      if (!empty($e->errorInfo[1]) && $e->errorInfo[1] === 17) {
-        // The schema has changed. SQLite specifies that we must resend the query.
-        $return = parent::execute($args, $options);
-      }
-      else {
-        // Rethrow the exception.
-        throw $e;
-      }
-    }
-
-    // In some weird cases, SQLite will prefix some column names by the name
-    // of the table. We post-process the data, by renaming the column names
-    // using the same convention as MySQL and PostgreSQL.
-    $rename_columns = array();
-    foreach ($this->columnNames as $k => $column) {
-      // In some SQLite versions, SELECT DISTINCT(field) will return "(field)"
-      // instead of "field".
-      if (preg_match("/^\((.*)\)$/", $column, $matches)) {
-        $rename_columns[$column] = $matches[1];
-        $this->columnNames[$k] = $matches[1];
-        $column = $matches[1];
-      }
-
-      // Remove "table." prefixes.
-      if (preg_match("/^.*\.(.*)$/", $column, $matches)) {
-        $rename_columns[$column] = $matches[1];
-        $this->columnNames[$k] = $matches[1];
-      }
-    }
-    if ($rename_columns) {
-      // DatabaseStatementPrefetch already extracted the first row,
-      // put it back into the result set.
-      if (isset($this->currentRow)) {
-        $this->data[0] = &$this->currentRow;
-      }
-
-      // Then rename all the columns across the result set.
-      foreach ($this->data as $k => $row) {
-        foreach ($rename_columns as $old_column => $new_column) {
-          $this->data[$k][$new_column] = $this->data[$k][$old_column];
-          unset($this->data[$k][$old_column]);
-        }
-      }
-
-      // Finally, extract the first row again.
-      $this->currentRow = $this->data[0];
-      unset($this->data[0]);
-    }
-
-    return $return;
-  }
-}
-
-/**
- * @} End of "ingroup database".
- */
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Delete.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Delete.php
new file mode 100644
index 0000000000000000000000000000000000000000..c0056cbe3816a78843c491c1ac04cabf0796566e
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Delete.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\sqlite\Delete
+ */
+
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\Query\Delete as QueryDelete;
+
+/**
+ * SQLite specific implementation of DeleteQuery.
+ *
+ * When the WHERE is omitted from a DELETE statement and the table being deleted
+ * has no triggers, SQLite uses an optimization to erase the entire table content
+ * without having to visit each row of the table individually.
+ *
+ * Prior to SQLite 3.6.5, SQLite does not return the actual number of rows deleted
+ * by that optimized "truncate" optimization.
+ */
+class Delete extends QueryDelete {
+  public function execute() {
+    if (!count($this->condition)) {
+      $total_rows = $this->connection->query('SELECT COUNT(*) FROM {' . $this->connection->escapeTable($this->table) . '}')->fetchField();
+      parent::execute();
+      return $total_rows;
+    }
+    else {
+      return parent::execute();
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Insert.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Insert.php
new file mode 100644
index 0000000000000000000000000000000000000000..e584943430bcd65e70dafb954f4322781869c058
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Insert.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\sqlite\Insert
+ */
+
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\Query\Insert as QueryInsert;
+
+/**
+ * SQLite specific implementation of InsertQuery.
+ *
+ * We ignore all the default fields and use the clever SQLite syntax:
+ *   INSERT INTO table DEFAULT VALUES
+ * for degenerated "default only" queries.
+ */
+class Insert extends QueryInsert {
+
+  public function execute() {
+    if (!$this->preExecute()) {
+      return NULL;
+    }
+    if (count($this->insertFields)) {
+      return parent::execute();
+    }
+    else {
+      return $this->connection->query('INSERT INTO {' . $this->table . '} DEFAULT VALUES', array(), $this->queryOptions);
+    }
+  }
+
+  public function __toString() {
+    // Create a sanitized comment string to prepend to the query.
+    $comments = $this->connection->makeComment($this->comments);
+
+    // Produce as many generic placeholders as necessary.
+    $placeholders = array_fill(0, count($this->insertFields), '?');
+
+    // If we're selecting from a SelectQuery, finish building the query and
+    // pass it back, as any remaining options are irrelevant.
+    if (!empty($this->fromQuery)) {
+      return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') ' . $this->fromQuery;
+    }
+
+    return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') VALUES (' . implode(', ', $placeholders) . ')';
+  }
+
+}
\ No newline at end of file
diff --git a/core/includes/database/sqlite/install.inc b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
similarity index 87%
rename from core/includes/database/sqlite/install.inc
rename to core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
index 62cbac381f17c5cad67688540e0ff9a58905caf2..8866ef22a53d1c38ce6b0c7241b0784e1d69aae4 100644
--- a/core/includes/database/sqlite/install.inc
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
@@ -2,10 +2,16 @@
 
 /**
  * @file
- * SQLite specific install functions
+ * Definition of Drupal\Core\Database\Driver\sqlite\Install\Tasks
  */
 
-class DatabaseTasks_sqlite extends DatabaseTasks {
+namespace Drupal\Core\Database\Driver\sqlite\Install;
+
+use Drupal\Core\Database\Install\Tasks as InstallTasks;
+
+use SplFileInfo;
+
+class Tasks extends InstallTasks {
   protected $pdoDriver = 'sqlite';
 
   public function name() {
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Merge.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Merge.php
new file mode 100644
index 0000000000000000000000000000000000000000..3bbc3de8c176ac1d11dd43dfcfccb3f10a9aa266
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Merge.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\sqlite\Merge
+ */
+
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\Query\Merge as QueryMerge;
+
+class Merge extends QueryMerge { }
diff --git a/core/includes/database/sqlite/schema.inc b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
similarity index 88%
rename from core/includes/database/sqlite/schema.inc
rename to core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
index c5882f12715d9c31933961c94b4f009ed773cccd..823cd137a166ef298786a083b817db8fd3290795 100644
--- a/core/includes/database/sqlite/schema.inc
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
@@ -2,16 +2,24 @@
 
 /**
  * @file
- * Database schema code for SQLite databases.
+ * Definition of Drupal\Core\Database\Driver\sqlite\Schema
  */
 
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\SchemaObjectExistsException;
+use Drupal\Core\Database\SchemaObjectDoesNotExistException;
+use Drupal\Core\Database\Schema as DatabaseSchema;
+
+use Exception;
+
 
 /**
  * @ingroup schemaapi
  * @{
  */
 
-class DatabaseSchema_sqlite extends DatabaseSchema {
+class Schema extends DatabaseSchema {
 
   /**
    * Override DatabaseSchema::$defaultSchema
@@ -232,10 +240,10 @@ public function getFieldTypeMap() {
 
   public function renameTable($table, $new_name) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename %table to %table_new: table %table doesn't exist.", array('%table' => $table, '%table_new' => $new_name)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot rename %table to %table_new: table %table doesn't exist.", array('%table' => $table, '%table_new' => $new_name)));
     }
     if ($this->tableExists($new_name)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot rename %table to %table_new: table %table_new already exists.", array('%table' => $table, '%table_new' => $new_name)));
+      throw new SchemaObjectExistsException(t("Cannot rename %table to %table_new: table %table_new already exists.", array('%table' => $table, '%table_new' => $new_name)));
     }
 
     $schema = $this->introspectSchema($table);
@@ -278,10 +286,10 @@ public function dropTable($table) {
 
   public function addField($table, $field, $specification, $keys_new = array()) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
     }
     if ($this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
+      throw new SchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
     }
 
     // SQLite doesn't have a full-featured ALTER TABLE statement. It only
@@ -494,10 +502,10 @@ public function dropField($table, $field) {
 
   public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
     if (!$this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot change the definition of field %table.%name: field doesn't exist.", array('%table' => $table, '%name' => $field)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot change the definition of field %table.%name: field doesn't exist.", array('%table' => $table, '%name' => $field)));
     }
     if (($field != $field_new) && $this->fieldExists($table, $field_new)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot rename field %table.%name to %name_new: target field already exists.", array('%table' => $table, '%name' => $field, '%name_new' => $field_new)));
+      throw new SchemaObjectExistsException(t("Cannot rename field %table.%name to %name_new: target field already exists.", array('%table' => $table, '%name' => $field, '%name_new' => $field_new)));
     }
 
     $old_schema = $this->introspectSchema($table);
@@ -559,10 +567,10 @@ protected function mapKeyDefinition(array $key_definition, array $mapping) {
 
   public function addIndex($table, $name, $fields) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add index %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add index %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
     }
     if ($this->indexExists($table, $name)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
     }
 
     $schema['indexes'][$name] = $fields;
@@ -591,10 +599,10 @@ public function dropIndex($table, $name) {
 
   public function addUniqueKey($table, $name, $fields) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add unique key %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add unique key %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
     }
     if ($this->indexExists($table, $name)) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
+      throw new SchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
     }
 
     $schema['unique keys'][$name] = $fields;
@@ -617,14 +625,14 @@ public function dropUniqueKey($table, $name) {
 
   public function addPrimaryKey($table, $fields) {
     if (!$this->tableExists($table)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add primary key to table %table: table doesn't exist.", array('%table' => $table)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot add primary key to table %table: table doesn't exist.", array('%table' => $table)));
     }
 
     $old_schema = $this->introspectSchema($table);
     $new_schema = $old_schema;
 
     if (!empty($new_schema['primary key'])) {
-      throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
+      throw new SchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
     }
 
     $new_schema['primary key'] = $fields;
@@ -646,7 +654,7 @@ public function dropPrimaryKey($table) {
 
   public function fieldSetDefault($table, $field, $default) {
     if (!$this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
     $old_schema = $this->introspectSchema($table);
@@ -658,7 +666,7 @@ public function fieldSetDefault($table, $field, $default) {
 
   public function fieldSetNoDefault($table, $field) {
     if (!$this->fieldExists($table, $field)) {
-      throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
+      throw new SchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
     $old_schema = $this->introspectSchema($table);
@@ -680,4 +688,4 @@ public function findTables($table_expression) {
     ));
     return $result->fetchAllKeyed(0, 0);
   }
-}
+}
\ No newline at end of file
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Select.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Select.php
new file mode 100644
index 0000000000000000000000000000000000000000..5403611003c94908fd8d866717b0caea9e47ff59
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Select.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\sqlite\Select
+ */
+
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\Query\Select as QuerySelect;
+
+class Select extends QuerySelect {
+  public function forUpdate($set = TRUE) {
+    // SQLite does not support FOR UPDATE so nothing to do.
+    return $this;
+  }
+}
\ No newline at end of file
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php
new file mode 100644
index 0000000000000000000000000000000000000000..531b6d08b249732fb0b40db064198b5a22a27e54
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php
@@ -0,0 +1,148 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\sqlite\Statement
+ */
+
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\StatementPrefetch;
+use Drupal\Core\Database\StatementInterface;
+
+use Iterator;
+use PDOException;
+
+/**
+ * Specific SQLite implementation of DatabaseConnection.
+ *
+ * See DatabaseConnection_sqlite::PDOPrepare() for reasons why we must prefetch
+ * the data instead of using PDOStatement.
+ *
+ * @see DatabaseConnection_sqlite::PDOPrepare()
+ */
+class Statement extends StatementPrefetch implements Iterator, StatementInterface {
+
+  /**
+   * SQLite specific implementation of getStatement().
+   *
+   * The PDO SQLite layer doesn't replace numeric placeholders in queries
+   * correctly, and this makes numeric expressions (such as COUNT(*) >= :count)
+   * fail. We replace numeric placeholders in the query ourselves to work
+   * around this bug.
+   *
+   * See http://bugs.php.net/bug.php?id=45259 for more details.
+   */
+  protected function getStatement($query, &$args = array()) {
+    if (count($args)) {
+      // Check if $args is a simple numeric array.
+      if (range(0, count($args) - 1) === array_keys($args)) {
+        // In that case, we have unnamed placeholders.
+        $count = 0;
+        $new_args = array();
+        foreach ($args as $value) {
+          if (is_float($value) || is_int($value)) {
+            if (is_float($value)) {
+              // Force the conversion to float so as not to loose precision
+              // in the automatic cast.
+              $value = sprintf('%F', $value);
+            }
+            $query = substr_replace($query, $value, strpos($query, '?'), 1);
+          }
+          else {
+            $placeholder = ':db_statement_placeholder_' . $count++;
+            $query = substr_replace($query, $placeholder, strpos($query, '?'), 1);
+            $new_args[$placeholder] = $value;
+          }
+        }
+        $args = $new_args;
+      }
+      else {
+        // Else, this is using named placeholders.
+        foreach ($args as $placeholder => $value) {
+          if (is_float($value) || is_int($value)) {
+            if (is_float($value)) {
+              // Force the conversion to float so as not to loose precision
+              // in the automatic cast.
+              $value = sprintf('%F', $value);
+            }
+
+            // We will remove this placeholder from the query as PDO throws an
+            // exception if the number of placeholders in the query and the
+            // arguments does not match.
+            unset($args[$placeholder]);
+            // PDO allows placeholders to not be prefixed by a colon. See
+            // http://marc.info/?l=php-internals&m=111234321827149&w=2 for
+            // more.
+            if ($placeholder[0] != ':') {
+              $placeholder = ":$placeholder";
+            }
+            // When replacing the placeholders, make sure we search for the
+            // exact placeholder. For example, if searching for
+            // ':db_placeholder_1', do not replace ':db_placeholder_11'.
+            $query = preg_replace('/' . preg_quote($placeholder) . '\b/', $value, $query);
+          }
+        }
+      }
+    }
+
+    return $this->dbh->PDOPrepare($query);
+  }
+
+  public function execute($args = array(), $options = array()) {
+    try {
+      $return = parent::execute($args, $options);
+    }
+    catch (PDOException $e) {
+      if (!empty($e->errorInfo[1]) && $e->errorInfo[1] === 17) {
+        // The schema has changed. SQLite specifies that we must resend the query.
+        $return = parent::execute($args, $options);
+      }
+      else {
+        // Rethrow the exception.
+        throw $e;
+      }
+    }
+
+    // In some weird cases, SQLite will prefix some column names by the name
+    // of the table. We post-process the data, by renaming the column names
+    // using the same convention as MySQL and PostgreSQL.
+    $rename_columns = array();
+    foreach ($this->columnNames as $k => $column) {
+      // In some SQLite versions, SELECT DISTINCT(field) will return "(field)"
+      // instead of "field".
+      if (preg_match("/^\((.*)\)$/", $column, $matches)) {
+        $rename_columns[$column] = $matches[1];
+        $this->columnNames[$k] = $matches[1];
+        $column = $matches[1];
+      }
+
+      // Remove "table." prefixes.
+      if (preg_match("/^.*\.(.*)$/", $column, $matches)) {
+        $rename_columns[$column] = $matches[1];
+        $this->columnNames[$k] = $matches[1];
+      }
+    }
+    if ($rename_columns) {
+      // DatabaseStatementPrefetch already extracted the first row,
+      // put it back into the result set.
+      if (isset($this->currentRow)) {
+        $this->data[0] = &$this->currentRow;
+      }
+
+      // Then rename all the columns across the result set.
+      foreach ($this->data as $k => $row) {
+        foreach ($rename_columns as $old_column => $new_column) {
+          $this->data[$k][$new_column] = $this->data[$k][$old_column];
+          unset($this->data[$k][$old_column]);
+        }
+      }
+
+      // Finally, extract the first row again.
+      $this->currentRow = $this->data[0];
+      unset($this->data[0]);
+    }
+
+    return $return;
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Transaction.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Transaction.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae73ed8c98799984a4878bd53d56ef770f17fcda
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Transaction.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\sqlite\Transaction
+ */
+
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\Transaction as DatabaseTransaction;
+
+class Transaction extends DatabaseTransaction { }
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Truncate.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Truncate.php
new file mode 100644
index 0000000000000000000000000000000000000000..bc635404447f94f1e880f09265e27797f35f05ff
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Truncate.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\sqlite\Truncate
+ */
+
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\Query\Truncate as QueryTruncate;
+
+/**
+ * SQLite specific implementation of TruncateQuery.
+ *
+ * SQLite doesn't support TRUNCATE, but a DELETE query with no condition has
+ * exactly the effect (it is implemented by DROPing the table).
+ */
+class Truncate extends QueryTruncate {
+  public function __toString() {
+    // Create a sanitized comment string to prepend to the query.
+    $comments = $this->connection->makeComment($this->comments);
+
+    return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '} ';
+  }
+}
\ No newline at end of file
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Update.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Update.php
new file mode 100644
index 0000000000000000000000000000000000000000..18332e7d5578eddf430da2a57604d34583c050e0
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Update.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Driver\sqlite\Update
+ */
+
+namespace Drupal\Core\Database\Driver\sqlite;
+
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\Query\ConditionInterface;
+use Drupal\Core\Database\Query\Update as QueryUpdate;
+
+/**
+ * SQLite specific implementation of UpdateQuery.
+ *
+ * SQLite counts all the rows that match the conditions as modified, even if they
+ * will not be affected by the query. We workaround this by ensuring that
+ * we don't select those rows.
+ *
+ * A query like this one:
+ *   UPDATE test SET name = 'newname' WHERE tid = 1
+ * will become:
+ *   UPDATE test SET name = 'newname' WHERE tid = 1 AND name <> 'newname'
+ */
+class Update extends QueryUpdate {
+  /**
+   * Helper function that removes the fields that are already in a condition.
+   *
+   * @param $fields
+   *   The fields.
+   * @param QueryConditionInterface $condition
+   *   A database condition.
+   */
+  protected function removeFieldsInCondition(&$fields, ConditionInterface $condition) {
+    foreach ($condition->conditions() as $child_condition) {
+      if ($child_condition['field'] instanceof ConditionInterface) {
+        $this->removeFieldsInCondition($fields, $child_condition['field']);
+      }
+      else {
+        unset($fields[$child_condition['field']]);
+      }
+    }
+  }
+
+  public function execute() {
+    if (!empty($this->queryOptions['sqlite_return_matched_rows'])) {
+      return parent::execute();
+    }
+
+    // Get the fields used in the update query, and remove those that are already
+    // in the condition.
+    $fields = $this->expressionFields + $this->fields;
+    $this->removeFieldsInCondition($fields, $this->condition);
+
+    // Add the inverse of the fields to the condition.
+    $condition = new Condition('OR');
+    foreach ($fields as $field => $data) {
+      if (is_array($data)) {
+        // The field is an expression.
+        $condition->where($field . ' <> ' . $data['expression']);
+        $condition->isNull($field);
+      }
+      elseif (!isset($data)) {
+        // The field will be set to NULL.
+        $condition->isNotNull($field);
+      }
+      else {
+        $condition->condition($field, $data, '<>');
+        $condition->isNull($field);
+      }
+    }
+    if (count($condition)) {
+      $condition->compile($this->connection, $this);
+      $this->condition->where((string) $condition, $condition->arguments());
+    }
+    return parent::execute();
+  }
+
+}
\ No newline at end of file
diff --git a/core/lib/Drupal/Core/Database/DriverNotSpecifiedException.php b/core/lib/Drupal/Core/Database/DriverNotSpecifiedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..946393142cc09e2c06ff2c95b466474728905f4e
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/DriverNotSpecifiedException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\DriverNotSpecifiedException
+ */
+
+namespace Drupal\Core\Database;
+
+use RuntimeException;
+
+/**
+ * Exception thrown if no driver is specified for a database connection.
+ */
+class DriverNotSpecifiedException extends RuntimeException {}
diff --git a/core/lib/Drupal/Core/Database/Install/TaskException.php b/core/lib/Drupal/Core/Database/Install/TaskException.php
new file mode 100644
index 0000000000000000000000000000000000000000..d93b736c00210ea914cbdc2489cfdef0fba28e16
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Install/TaskException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Install\TaskException
+ */
+
+namespace Drupal\Core\Database\Install;
+
+use RuntimeException;
+
+/**
+ * Exception thrown if the database installer fails.
+ */
+class TaskException extends RuntimeException { }
diff --git a/core/lib/Drupal/Core/Database/Install/Tasks.php b/core/lib/Drupal/Core/Database/Install/Tasks.php
new file mode 100644
index 0000000000000000000000000000000000000000..ece3c7c251931d458802fbd340da2275fb1ce837
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Install/Tasks.php
@@ -0,0 +1,305 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Install\Tasks
+ */
+
+namespace Drupal\Core\Database\Install;
+
+use Drupal\Core\Database\Database;
+
+use PDO;
+
+/**
+ * Database installer structure.
+ *
+ * Defines basic Drupal requirements for databases.
+ */
+abstract class Tasks {
+
+  /**
+   * Structure that describes each task to run.
+   *
+   * @var array
+   *
+   * Each value of the tasks array is an associative array defining the function
+   * to call (optional) and any arguments to be passed to the function.
+   */
+  protected $tasks = array(
+    array(
+      'function'    => 'checkEngineVersion',
+      'arguments'   => array(),
+    ),
+    array(
+      'arguments'   => array(
+        'CREATE TABLE {drupal_install_test} (id int NULL)',
+        'Drupal can use CREATE TABLE database commands.',
+        'Failed to <strong>CREATE</strong> a test table on your database server with the command %query. The server reports the following message: %error.<p>Are you sure the configured username has the necessary permissions to create tables in the database?</p>',
+        TRUE,
+      ),
+    ),
+    array(
+      'arguments'   => array(
+        'INSERT INTO {drupal_install_test} (id) VALUES (1)',
+        'Drupal can use INSERT database commands.',
+        'Failed to <strong>INSERT</strong> a value into a test table on your database server. We tried inserting a value with the command %query and the server reported the following error: %error.',
+      ),
+    ),
+    array(
+      'arguments'   => array(
+        'UPDATE {drupal_install_test} SET id = 2',
+        'Drupal can use UPDATE database commands.',
+        'Failed to <strong>UPDATE</strong> a value in a test table on your database server. We tried updating a value with the command %query and the server reported the following error: %error.',
+      ),
+    ),
+    array(
+      'arguments'   => array(
+        'DELETE FROM {drupal_install_test}',
+        'Drupal can use DELETE database commands.',
+        'Failed to <strong>DELETE</strong> a value from a test table on your database server. We tried deleting a value with the command %query and the server reported the following error: %error.',
+      ),
+    ),
+    array(
+      'arguments'   => array(
+        'DROP TABLE {drupal_install_test}',
+        'Drupal can use DROP TABLE database commands.',
+        'Failed to <strong>DROP</strong> a test table from your database server. We tried dropping a table with the command %query and the server reported the following error %error.',
+      ),
+    ),
+  );
+
+  /**
+   * Results from tasks.
+   *
+   * @var array
+   */
+  protected $results = array();
+
+  /**
+   * Ensure the PDO driver is supported by the version of PHP in use.
+   */
+  protected function hasPdoDriver() {
+    return in_array($this->pdoDriver, PDO::getAvailableDrivers());
+  }
+
+  /**
+   * Assert test as failed.
+   */
+  protected function fail($message) {
+    $this->results[$message] = FALSE;
+  }
+
+  /**
+   * Assert test as a pass.
+   */
+  protected function pass($message) {
+    $this->results[$message] = TRUE;
+  }
+
+  /**
+   * Check whether Drupal is installable on the database.
+   */
+  public function installable() {
+    return $this->hasPdoDriver() && empty($this->error);
+  }
+
+  /**
+   * Return the human-readable name of the driver.
+   */
+  abstract public function name();
+
+  /**
+   * Return the minimum required version of the engine.
+   *
+   * @return
+   *   A version string. If not NULL, it will be checked against the version
+   *   reported by the Database engine using version_compare().
+   */
+  public function minimumVersion() {
+    return NULL;
+  }
+
+  /**
+   * Run database tasks and tests to see if Drupal can run on the database.
+   */
+  public function runTasks() {
+    // We need to establish a connection before we can run tests.
+    if ($this->connect()) {
+      foreach ($this->tasks as $task) {
+        if (!isset($task['function'])) {
+          $task['function'] = 'runTestQuery';
+        }
+        if (method_exists($this, $task['function'])) {
+          // Returning false is fatal. No other tasks can run.
+          if (FALSE === call_user_func_array(array($this, $task['function']), $task['arguments'])) {
+            break;
+          }
+        }
+        else {
+          throw new TaskException(st("Failed to run all tasks against the database server. The task %task wasn't found.", array('%task' => $task['function'])));
+        }
+      }
+    }
+    // Check for failed results and compile message
+    $message = '';
+    foreach ($this->results as $result => $success) {
+      if (!$success) {
+        $message .= '<p class="error">' . $result  . '</p>';
+      }
+    }
+    if (!empty($message)) {
+      $message = '<p>In order for Drupal to work, and to continue with the installation process, you must resolve all issues reported below. For more help with configuring your database server, see the <a href="http://drupal.org/getting-started/install">installation handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.</p>' . $message;
+      throw new TaskException($message);
+    }
+  }
+
+  /**
+   * Check if we can connect to the database.
+   */
+  protected function connect() {
+    try {
+      // This doesn't actually test the connection.
+      db_set_active();
+      // Now actually do a check.
+      Database::getConnection();
+      $this->pass('Drupal can CONNECT to the database ok.');
+    }
+    catch (Exception $e) {
+      $this->fail(st('Failed to connect to your database server. The server reports the following message: %error.<ul><li>Is the database server running?</li><li>Does the database exist, and have you entered the correct database name?</li><li>Have you entered the correct username and password?</li><li>Have you entered the correct database hostname?</li></ul>', array('%error' => $e->getMessage())));
+      return FALSE;
+    }
+    return TRUE;
+  }
+
+  /**
+   * Run SQL tests to ensure the database can execute commands with the current user.
+   */
+  protected function runTestQuery($query, $pass, $fail, $fatal = FALSE) {
+    try {
+      db_query($query);
+      $this->pass(st($pass));
+    }
+    catch (Exception $e) {
+      $this->fail(st($fail, array('%query' => $query, '%error' => $e->getMessage(), '%name' => $this->name())));
+      return !$fatal;
+    }
+  }
+
+  /**
+   * Check the engine version.
+   */
+  protected function checkEngineVersion() {
+    if ($this->minimumVersion() && version_compare(Database::getConnection()->version(), $this->minimumVersion(), '<')) {
+      $this->fail(st("The database version %version is less than the minimum required version %minimum_version.", array('%version' => Database::getConnection()->version(), '%minimum_version' => $this->minimumVersion())));
+    }
+  }
+
+  /**
+   * Return driver specific configuration options.
+   *
+   * @param $database
+   *  An array of driver specific configuration options.
+   *
+   * @return
+   *   The options form array.
+   */
+  public function getFormOptions($database) {
+    $form['database'] = array(
+      '#type' => 'textfield',
+      '#title' => st('Database name'),
+      '#default_value' => empty($database['database']) ? '' : $database['database'],
+      '#size' => 45,
+      '#required' => TRUE,
+      '#description' => st('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => drupal_install_profile_distribution_name())),
+    );
+
+    $form['username'] = array(
+      '#type' => 'textfield',
+      '#title' => st('Database username'),
+      '#default_value' => empty($database['username']) ? '' : $database['username'],
+      '#required' => TRUE,
+      '#size' => 45,
+    );
+
+    $form['password'] = array(
+      '#type' => 'password',
+      '#title' => st('Database password'),
+      '#default_value' => empty($database['password']) ? '' : $database['password'],
+      '#required' => FALSE,
+      '#size' => 45,
+    );
+
+    $form['advanced_options'] = array(
+      '#type' => 'fieldset',
+      '#title' => st('Advanced options'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#description' => st("These options are only necessary for some sites. If you're not sure what you should enter here, leave the default settings or check with your hosting provider."),
+      '#weight' => 10,
+    );
+
+    $profile = drupal_get_profile();
+    $db_prefix = ($profile == 'standard') ? 'drupal_' : $profile . '_';
+    $form['advanced_options']['db_prefix'] = array(
+      '#type' => 'textfield',
+      '#title' => st('Table prefix'),
+      '#default_value' => '',
+      '#size' => 45,
+      '#description' => st('If more than one application will be sharing this database, enter a table prefix such as %prefix for your @drupal site here.', array('@drupal' => drupal_install_profile_distribution_name(), '%prefix' => $db_prefix)),
+      '#weight' => 10,
+    );
+
+    $form['advanced_options']['host'] = array(
+      '#type' => 'textfield',
+      '#title' => st('Database host'),
+      '#default_value' => empty($database['host']) ? 'localhost' : $database['host'],
+      '#size' => 45,
+      // Hostnames can be 255 characters long.
+      '#maxlength' => 255,
+      '#required' => TRUE,
+      '#description' => st('If your database is located on a different server, change this.'),
+    );
+
+    $form['advanced_options']['port'] = array(
+      '#type' => 'textfield',
+      '#title' => st('Database port'),
+      '#default_value' => empty($database['port']) ? '' : $database['port'],
+      '#size' => 45,
+      // The maximum port number is 65536, 5 digits.
+      '#maxlength' => 5,
+      '#description' => st('If your database server is listening to a non-standard port, enter its number.'),
+    );
+
+    return $form;
+  }
+
+  /**
+   * Validates driver specific configuration settings.
+   *
+   * Checks to ensure correct basic database settings and that a proper
+   * connection to the database can be established.
+   *
+   * @param $database
+   *   An array of driver specific configuration options.
+   *
+   * @return
+   *   An array of driver configuration errors, keyed by form element name.
+   */
+  public function validateDatabaseSettings($database) {
+    $errors = array();
+
+    // Verify the table prefix.
+    if (!empty($database['prefix']) && is_string($database['prefix']) && !preg_match('/^[A-Za-z0-9_.]+$/', $database['prefix'])) {
+      $errors[$database['driver'] . '][advanced_options][db_prefix'] = st('The database table prefix you have entered, %prefix, is invalid. The table prefix can only contain alphanumeric characters, periods, or underscores.', array('%prefix' => $database['prefix']));
+    }
+
+    // Verify the database port.
+    if (!empty($database['port']) && !is_numeric($database['port'])) {
+      $errors[$database['driver'] . '][advanced_options][port'] =  st('Database port must be a number.');
+    }
+
+    return $errors;
+  }
+
+}
diff --git a/core/includes/database/log.inc b/core/lib/Drupal/Core/Database/Log.php
similarity index 80%
rename from core/includes/database/log.inc
rename to core/lib/Drupal/Core/Database/Log.php
index ec27ef8e6332ad6543ce7b489b0048b4aa3a8034..5d5d560c152157491cdd3868f75413422b3dedc1 100644
--- a/core/includes/database/log.inc
+++ b/core/lib/Drupal/Core/Database/Log.php
@@ -2,9 +2,11 @@
 
 /**
  * @file
- * Logging classes for the database layer.
+ * Definition of Drupal\Core\Database\Log
  */
 
+namespace Drupal\Core\Database;
+
 /**
  * Database query logger.
  *
@@ -16,7 +18,7 @@
  * Every connection has one and only one logging object on it for all targets
  * and logging keys.
  */
-class DatabaseLog {
+class Log {
 
   /**
    * Cache of logged queries. This will only be used if the query logger is enabled.
@@ -112,7 +114,7 @@ public function end($logging_key) {
    * @param $time
    *   The time in milliseconds the query took to execute.
    */
-  public function log(DatabaseStatementInterface $statement, $args, $time) {
+  public function log(StatementInterface $statement, $args, $time) {
     foreach (array_keys($this->queryLog) as $key) {
       $this->queryLog[$key][] = array(
         'query' => $statement->getQueryString(),
@@ -128,9 +130,12 @@ public function log(DatabaseStatementInterface $statement, $args, $time) {
    * Determine the routine that called this query.
    *
    * We define "the routine that called this query" as the first entry in
-   * the call stack that is not inside includes/database. That makes the
-   * climbing logic very simple, and handles the variable stack depth caused
-   * by the query builders.
+   * the call stack that is not inside the includes/Drupal/Database directory
+   * and does not begin with db_. That makes the climbing logic very simple, and
+   * handles the variable stack depth caused by the query builders.
+   *
+   * @todo Revisit this logic to not be dependent on file path, so that we can
+   *       split most of the DB layer out of Drupal.
    *
    * @link http://www.php.net/debug_backtrace
    * @return
@@ -142,9 +147,14 @@ public function log(DatabaseStatementInterface $statement, $args, $time) {
    */
   public function findCaller() {
     $stack = debug_backtrace();
-    $stack_count = count($stack);
-    for ($i = 0; $i < $stack_count; ++$i) {
-      if (strpos($stack[$i]['file'], 'includes' . DIRECTORY_SEPARATOR . 'database') === FALSE) {
+    for ($i = 0, $stack_count = count($stack); $i < $stack_count; ++$i) {
+      // If the call was made from a function, 'class' will be empty. It's
+      // just easier to give it a default value than to try and integrate
+      // that into the if statement below.
+      if (empty($stack[$i]['class'])) {
+        $stack[$i]['class'] = '';
+      }
+      if (strpos($stack[$i]['class'], __NAMESPACE__) === FALSE && strpos($stack[$i + 1]['function'], 'db_') === FALSE) {
         return array(
           'file' => $stack[$i]['file'],
           'line' => $stack[$i]['line'],
diff --git a/core/lib/Drupal/Core/Database/Query/AlterableInterface.php b/core/lib/Drupal/Core/Database/Query/AlterableInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..66a41e2e32719d31243220a27ddfdf028ed8c70c
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/AlterableInterface.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\AlterableInterface
+ */
+
+namespace Drupal\Core\Database\Query;
+
+/**
+ * Interface for a query that can be manipulated via an alter hook.
+ */
+interface AlterableInterface {
+
+  /**
+   * Adds a tag to a query.
+   *
+   * Tags are strings that identify a query. A query may have any number of
+   * tags. Tags are used to mark a query so that alter hooks may decide if they
+   * wish to take action. Tags should be all lower-case and contain only
+   * letters, numbers, and underscore, and start with a letter. That is, they
+   * should follow the same rules as PHP identifiers in general.
+   *
+   * @param $tag
+   *   The tag to add.
+   *
+   * @return Drupal\Core\Database\Query\AlterableInterface
+   *   The called object.
+   */
+  public function addTag($tag);
+
+  /**
+   * Determines if a given query has a given tag.
+   *
+   * @param $tag
+   *   The tag to check.
+   *
+   * @return
+   *   TRUE if this query has been marked with this tag, FALSE otherwise.
+   */
+  public function hasTag($tag);
+
+  /**
+   * Determines if a given query has all specified tags.
+   *
+   * @param $tags
+   *   A variable number of arguments, one for each tag to check.
+   *
+   * @return
+   *   TRUE if this query has been marked with all specified tags, FALSE
+   *   otherwise.
+   */
+  public function hasAllTags();
+
+  /**
+   * Determines if a given query has any specified tag.
+   *
+   * @param $tags
+   *   A variable number of arguments, one for each tag to check.
+   *
+   * @return
+   *   TRUE if this query has been marked with at least one of the specified
+   *   tags, FALSE otherwise.
+   */
+  public function hasAnyTag();
+
+  /**
+   * Adds additional metadata to the query.
+   *
+   * Often, a query may need to provide additional contextual data to alter
+   * hooks. Alter hooks may then use that information to decide if and how
+   * to take action.
+   *
+   * @param $key
+   *   The unique identifier for this piece of metadata. Must be a string that
+   *   follows the same rules as any other PHP identifier.
+   * @param $object
+   *   The additional data to add to the query. May be any valid PHP variable.
+   *
+   * @return Drupal\Core\Database\Query\AlterableInterface
+   *   The called object.
+   */
+  public function addMetaData($key, $object);
+
+  /**
+   * Retrieves a given piece of metadata.
+   *
+   * @param $key
+   *   The unique identifier for the piece of metadata to retrieve.
+   *
+   * @return
+   *   The previously attached metadata object, or NULL if one doesn't exist.
+   */
+  public function getMetaData($key);
+}
diff --git a/core/lib/Drupal/Core/Database/Query/Condition.php b/core/lib/Drupal/Core/Database/Query/Condition.php
new file mode 100644
index 0000000000000000000000000000000000000000..9faabc6fb3b5b3d2722713def33f0af0045c4114
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/Condition.php
@@ -0,0 +1,317 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\Condition
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Connection;
+
+use Countable;
+
+/**
+ * Generic class for a series of conditions in a query.
+ */
+class Condition implements ConditionInterface, Countable {
+
+  /**
+   * Array of conditions.
+   *
+   * @var array
+   */
+  protected $conditions = array();
+
+  /**
+   * Array of arguments.
+   *
+   * @var array
+   */
+  protected $arguments = array();
+
+  /**
+   * Whether the conditions have been changed.
+   *
+   * TRUE if the condition has been changed since the last compile.
+   * FALSE if the condition has been compiled and not changed.
+   *
+   * @var bool
+   */
+  protected $changed = TRUE;
+
+  /**
+   * The identifier of the query placeholder this condition has been compiled against.
+   */
+  protected $queryPlaceholderIdentifier;
+
+  /**
+   * Constructs a Condition object.
+   *
+   * @param string $conjunction
+   *   The operator to use to combine conditions: 'AND' or 'OR'.
+   */
+  public function __construct($conjunction) {
+    $this->conditions['#conjunction'] = $conjunction;
+  }
+
+  /**
+   * Implements Countable::count().
+   *
+   * Returns the size of this conditional. The size of the conditional is the
+   * size of its conditional array minus one, because one element is the the
+   * conjunction.
+   */
+  public function count() {
+    return count($this->conditions) - 1;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::condition().
+   */
+  public function condition($field, $value = NULL, $operator = NULL) {
+    if (!isset($operator)) {
+      if (is_array($value)) {
+        $operator = 'IN';
+      }
+      else {
+        $operator = '=';
+      }
+    }
+    $this->conditions[] = array(
+      'field' => $field,
+      'value' => $value,
+      'operator' => $operator,
+    );
+
+    $this->changed = TRUE;
+
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::where().
+   */
+  public function where($snippet, $args = array()) {
+    $this->conditions[] = array(
+      'field' => $snippet,
+      'value' => $args,
+      'operator' => NULL,
+    );
+    $this->changed = TRUE;
+
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::isNull().
+   */
+  public function isNull($field) {
+    return $this->condition($field, NULL, 'IS NULL');
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::isNotNull().
+   */
+  public function isNotNull($field) {
+    return $this->condition($field, NULL, 'IS NOT NULL');
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::exists().
+   */
+  public function exists(SelectInterface $select) {
+    return $this->condition('', $select, 'EXISTS');
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::notExists().
+   */
+  public function notExists(SelectInterface $select) {
+    return $this->condition('', $select, 'NOT EXISTS');
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::conditions().
+   */
+  public function &conditions() {
+    return $this->conditions;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::arguments().
+   */
+  public function arguments() {
+    // If the caller forgot to call compile() first, refuse to run.
+    if ($this->changed) {
+      return NULL;
+    }
+    return $this->arguments;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compile().
+   */
+  public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
+    // Re-compile if this condition changed or if we are compiled against a
+    // different query placeholder object.
+    if ($this->changed || isset($this->queryPlaceholderIdentifier) && ($this->queryPlaceholderIdentifier != $queryPlaceholder->uniqueIdentifier())) {
+      $this->queryPlaceholderIdentifier = $queryPlaceholder->uniqueIdentifier();
+
+      $condition_fragments = array();
+      $arguments = array();
+
+      $conditions = $this->conditions;
+      $conjunction = $conditions['#conjunction'];
+      unset($conditions['#conjunction']);
+      foreach ($conditions as $condition) {
+        if (!empty($GLOBALS['lg'])) debug($condition);
+        if (empty($condition['operator'])) {
+          // This condition is a literal string, so let it through as is.
+          $condition_fragments[] = ' (' . $condition['field'] . ') ';
+          $arguments += $condition['value'];
+        }
+        else {
+          // It's a structured condition, so parse it out accordingly.
+          // Note that $condition['field'] will only be an object for a dependent
+          // DatabaseCondition object, not for a dependent subquery.
+          if ($condition['field'] instanceof ConditionInterface) {
+            // Compile the sub-condition recursively and add it to the list.
+            $condition['field']->compile($connection, $queryPlaceholder);
+            $condition_fragments[] = '(' . (string) $condition['field'] . ')';
+            $arguments += $condition['field']->arguments();
+          }
+          else {
+            // For simplicity, we treat all operators as the same data structure.
+            // In the typical degenerate case, this won't get changed.
+            $operator_defaults = array(
+              'prefix' => '',
+              'postfix' => '',
+              'delimiter' => '',
+              'operator' => $condition['operator'],
+              'use_value' => TRUE,
+            );
+            $operator = $connection->mapConditionOperator($condition['operator']);
+            if (!isset($operator)) {
+              $operator = $this->mapConditionOperator($condition['operator']);
+            }
+            $operator += $operator_defaults;
+
+            $placeholders = array();
+            if ($condition['value'] instanceof SelectInterface) {
+              $condition['value']->compile($connection, $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;
+            }
+            // We assume that if there is a delimiter, then the value is an
+            // array. If not, it is a scalar. For simplicity, we first convert
+            // up to an array so that we can build the placeholders in the same way.
+            elseif (!$operator['delimiter']) {
+              $condition['value'] = array($condition['value']);
+            }
+            if ($operator['use_value']) {
+              foreach ($condition['value'] as $value) {
+                $placeholder = ':db_condition_placeholder_' . $queryPlaceholder->nextPlaceholder();
+                $arguments[$placeholder] = $value;
+                $placeholders[] = $placeholder;
+              }
+            }
+            $condition_fragments[] = ' (' . $connection->escapeField($condition['field']) . ' ' . $operator['operator'] . ' ' . $operator['prefix'] . implode($operator['delimiter'], $placeholders) . $operator['postfix'] . ') ';
+          }
+        }
+      }
+
+      $this->changed = FALSE;
+      $this->stringVersion = implode($conjunction, $condition_fragments);
+      $this->arguments = $arguments;
+    }
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compiled().
+   */
+  public function compiled() {
+    return !$this->changed;
+  }
+
+  /**
+   * Implements PHP magic __toString method to convert the conditions to string.
+   *
+   * @return string
+   *   A string version of the conditions.
+   */
+  public function __toString() {
+    // If the caller forgot to call compile() first, refuse to run.
+    if ($this->changed) {
+      return '';
+    }
+    return $this->stringVersion;
+  }
+
+  /**
+   * PHP magic __clone() method.
+   *
+   * Only copies fields that implement Drupal\Core\Database\Query\ConditionInterface. Also sets
+   * $this->changed to TRUE.
+   */
+  function __clone() {
+    $this->changed = TRUE;
+    foreach ($this->conditions as $key => $condition) {
+      if ($condition['field'] instanceOf ConditionInterface) {
+        $this->conditions[$key]['field'] = clone($condition['field']);
+      }
+    }
+  }
+
+  /**
+   * Gets any special processing requirements for the condition operator.
+   *
+   * Some condition types require special processing, such as IN, because
+   * the value data they pass in is not a simple value. This is a simple
+   * overridable lookup function.
+   *
+   * @param $operator
+   *   The condition operator, such as "IN", "BETWEEN", etc. Case-sensitive.
+   *
+   * @return
+   *   The extra handling directives for the specified operator, or NULL.
+   */
+  protected function mapConditionOperator($operator) {
+    // $specials does not use drupal_static as its value never changes.
+    static $specials = array(
+      'BETWEEN' => array('delimiter' => ' AND '),
+      'IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
+      'NOT IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
+      'EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
+      'NOT EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
+      'IS NULL' => array('use_value' => FALSE),
+      'IS NOT NULL' => array('use_value' => FALSE),
+      // Use backslash for escaping wildcard characters.
+      'LIKE' => array('postfix' => " ESCAPE '\\\\'"),
+      'NOT LIKE' => array('postfix' => " ESCAPE '\\\\'"),
+      // These ones are here for performance reasons.
+      '=' => array(),
+      '<' => array(),
+      '>' => array(),
+      '>=' => array(),
+      '<=' => array(),
+    );
+    if (isset($specials[$operator])) {
+      $return = $specials[$operator];
+    }
+    else {
+      // We need to upper case because PHP index matches are case sensitive but
+      // do not need the more expensive drupal_strtoupper because SQL statements are ASCII.
+      $operator = strtoupper($operator);
+      $return = isset($specials[$operator]) ? $specials[$operator] : array();
+    }
+
+    $return += array('operator' => $operator);
+
+    return $return;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Database/Query/ConditionInterface.php b/core/lib/Drupal/Core/Database/Query/ConditionInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..70c23c785443dab1996f15f70842b5963b755eda
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/ConditionInterface.php
@@ -0,0 +1,159 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\ConditionInterface
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Connection;
+
+/**
+ * Interface for a conditional clause in a query.
+ */
+interface ConditionInterface {
+
+  /**
+   * Helper function: builds the most common conditional clauses.
+   *
+   * This method can take a variable number of parameters. If called with two
+   * parameters, they are taken as $field and $value with $operator having a
+   * value of IN if $value is an array and = otherwise.
+   *
+   * Do not use this method to test for NULL values. Instead, use
+   * QueryConditionInterface::isNull() or QueryConditionInterface::isNotNull().
+   *
+   * @param $field
+   *   The name of the field to check. If you would like to add a more complex
+   *   condition involving operators or functions, use where().
+   * @param $value
+   *   The value to test the field against. In most cases, this is a scalar.
+   *   For more complex options, it is an array. The meaning of each element in
+   *   the array is dependent on the $operator.
+   * @param $operator
+   *   The comparison operator, such as =, <, or >=. It also accepts more
+   *   complex options such as IN, LIKE, or BETWEEN. Defaults to IN if $value is
+   *   an array, and = otherwise.
+   *
+   * @return QueryConditionInterface
+   *   The called object.
+   *
+   * @see Drupal\Core\Database\Query\ConditionInterface::isNull()
+   * @see Drupal\Core\Database\Query\ConditionInterface::isNotNull()
+   */
+  public function condition($field, $value = NULL, $operator = NULL);
+
+  /**
+   * Adds an arbitrary WHERE clause to the query.
+   *
+   * @param $snippet
+   *   A portion of a WHERE clause as a prepared statement. It must use named
+   *   placeholders, not ? placeholders.
+   * @param $args
+   *   An associative array of arguments.
+   *
+   * @return Drupal\Core\Database\Query\ConditionInterface
+   *   The called object.
+   */
+  public function where($snippet, $args = array());
+
+  /**
+   * Sets a condition that the specified field be NULL.
+   *
+   * @param $field
+   *   The name of the field to check.
+   *
+   * @return Drupal\Core\Database\Query\ConditionInterface
+   *   The called object.
+   */
+  public function isNull($field);
+
+  /**
+   * Sets a condition that the specified field be NOT NULL.
+   *
+   * @param $field
+   *   The name of the field to check.
+   *
+   * @return Drupal\Core\Database\Query\ConditionInterface
+   *   The called object.
+   */
+  public function isNotNull($field);
+
+  /**
+   * Sets a condition that the specified subquery returns values.
+   *
+   * @param Drupal\Core\Database\Query\SelectInterface $select
+   *   The subquery that must contain results.
+   *
+   * @return Drupal\Core\Database\Query\ConditionInterface
+   *   The called object.
+   */
+  public function exists(SelectInterface $select);
+
+  /**
+   * Sets a condition that the specified subquery returns no values.
+   *
+   * @param Drupal\Core\Database\Query\SelectInterface $select
+   *   The subquery that must not contain results.
+   *
+   * @return Drupal\Core\Database\Query\ConditionInterface
+   *   The called object.
+   */
+  public function notExists(SelectInterface $select);
+
+  /**
+   * Gets a complete list of all conditions in this conditional clause.
+   *
+   * This method returns by reference. That allows alter hooks to access the
+   * data structure directly and manipulate it before it gets compiled.
+   *
+   * The data structure that is returned is an indexed array of entries, where
+   * each entry looks like the following:
+   * @code
+   * array(
+   *   'field' => $field,
+   *   'value' => $value,
+   *   'operator' => $operator,
+   * );
+   * @endcode
+   *
+   * In the special case that $operator is NULL, the $field is taken as a raw
+   * SQL snippet (possibly containing a function) and $value is an associative
+   * array of placeholders for the snippet.
+   *
+   * There will also be a single array entry of #conjunction, which is the
+   * conjunction that will be applied to the array, such as AND.
+   */
+  public function &conditions();
+
+  /**
+   * Gets a complete list of all values to insert into the prepared statement.
+   *
+   * @return
+   *   An associative array of placeholders and values.
+   */
+  public function arguments();
+
+  /**
+   * Compiles the saved conditions for later retrieval.
+   *
+   * This method does not return anything, but simply prepares data to be
+   * retrieved via __toString() and arguments().
+   *
+   * @param $connection
+   *   The database connection for which to compile the conditionals.
+   * @param $queryPlaceholder
+   *   The query this condition belongs to. If not given, the current query is
+   *   used.
+   */
+  public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder);
+
+  /**
+   * Check whether a condition has been previously compiled.
+   *
+   * @return
+   *   TRUE if the condition has been previously compiled.
+   */
+  public function compiled();
+}
diff --git a/core/lib/Drupal/Core/Database/Query/Delete.php b/core/lib/Drupal/Core/Database/Query/Delete.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ecd0407d75121aa071472dbdb60d7c0a171b6c2
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/Delete.php
@@ -0,0 +1,164 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\Delete
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection;
+
+/**
+ * General class for an abstracted DELETE operation.
+ */
+class Delete extends Query implements ConditionInterface {
+
+  /**
+   * The table from which to delete.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * The condition object for this query.
+   *
+   * Condition handling is handled via composition.
+   *
+   * @var Condition
+   */
+  protected $condition;
+
+  /**
+   * Constructs a Delete object.
+   *
+   * @param Drupal\Core\Database\Connection $connection
+   *   A DatabaseConnection object.
+   * @param string $table
+   *   Name of the table to associate with this query.
+   * @param array $options
+   *   Array of database options.
+   */
+  public function __construct(Connection $connection, $table, array $options = array()) {
+    $options['return'] = Database::RETURN_AFFECTED;
+    parent::__construct($connection, $options);
+    $this->table = $table;
+
+    $this->condition = new Condition('AND');
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::condition().
+   */
+  public function condition($field, $value = NULL, $operator = NULL) {
+    $this->condition->condition($field, $value, $operator);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::isNull().
+   */
+  public function isNull($field) {
+    $this->condition->isNull($field);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::isNotNull().
+   */
+  public function isNotNull($field) {
+    $this->condition->isNotNull($field);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::exists().
+   */
+  public function exists(SelectInterface $select) {
+    $this->condition->exists($select);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::notExists().
+   */
+  public function notExists(SelectInterface $select) {
+    $this->condition->notExists($select);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::conditions().
+   */
+  public function &conditions() {
+    return $this->condition->conditions();
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::arguments().
+   */
+  public function arguments() {
+    return $this->condition->arguments();
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::where().
+   */
+  public function where($snippet, $args = array()) {
+    $this->condition->where($snippet, $args);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compile().
+   */
+  public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
+    return $this->condition->compile($connection, $queryPlaceholder);
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compiled().
+   */
+  public function compiled() {
+    return $this->condition->compiled();
+  }
+
+  /**
+   * Executes the DELETE query.
+   *
+   * @return
+   *   The return value is dependent on the database connection.
+   */
+  public function execute() {
+    $values = array();
+    if (count($this->condition)) {
+      $this->condition->compile($this->connection, $this);
+      $values = $this->condition->arguments();
+    }
+
+    return $this->connection->query((string) $this, $values, $this->queryOptions);
+  }
+
+  /**
+   * Implements PHP magic __toString method to convert the query to a string.
+   *
+   * @return string
+   *   The prepared statement.
+   */
+  public function __toString() {
+    // Create a sanitized comment string to prepend to the query.
+    $comments = $this->connection->makeComment($this->comments);
+
+    $query = $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '} ';
+
+    if (count($this->condition)) {
+
+      $this->condition->compile($this->connection, $this);
+      $query .= "\nWHERE " . $this->condition;
+    }
+
+    return $query;
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Query/ExtendableInterface.php b/core/lib/Drupal/Core/Database/Query/ExtendableInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ebac45ac1983852b1bf15012ddfcafd6bc9660a
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/ExtendableInterface.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\ExtendableInterface
+ */
+
+namespace Drupal\Core\Database\Query;
+
+/**
+ * Interface for extendable query objects.
+ *
+ * "Extenders" follow the "Decorator" OOP design pattern.  That is, they wrap
+ * and "decorate" another object.  In our case, they implement the same interface
+ * as select queries and wrap a select query, to which they delegate almost all
+ * operations.  Subclasses of this class may implement additional methods or
+ * override existing methods as appropriate.  Extenders may also wrap other
+ * extender objects, allowing for arbitrarily complex "enhanced" queries.
+ */
+interface ExtendableInterface {
+
+  /**
+   * Enhance this object by wrapping it in an extender object.
+   *
+   * @param $extender_name
+   *   The base name of the extending class.  The base name will be checked
+   *   against the current database connection to allow driver-specific subclasses
+   *   as well, using the same logic as the query objects themselves.  For example,
+   *   PagerDefault_mysql is the MySQL-specific override for PagerDefault.
+   * @return Drupal\Core\Database\Query\ExtendableInterface
+   *   The extender object, which now contains a reference to this object.
+   */
+  public function extend($extender_name);
+}
diff --git a/core/lib/Drupal/Core/Database/Query/FieldsOverlapException.php b/core/lib/Drupal/Core/Database/Query/FieldsOverlapException.php
new file mode 100644
index 0000000000000000000000000000000000000000..f9d93728b158059da4e1ab5cd1559c8837afe187
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/FieldsOverlapException.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\FieldsOverlapExceptoin
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\DatabaseException;
+
+use InvalidArgumentException;
+
+/**
+ * Exception thrown if an insert query specifies a field twice.
+ *
+ * It is not allowed to specify a field as default and insert field, this
+ * exception is thrown if that is the case.
+ */
+class FieldsOverlapException extends InvalidArgumentException implements DatabaseException {}
diff --git a/core/lib/Drupal/Core/Database/Query/Insert.php b/core/lib/Drupal/Core/Database/Query/Insert.php
new file mode 100644
index 0000000000000000000000000000000000000000..e19de45cfa75319eca5abdc471bb9c3ef781da2d
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/Insert.php
@@ -0,0 +1,301 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\Insert
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Database;
+
+/**
+ * General class for an abstracted INSERT query.
+ */
+class Insert extends Query {
+
+  /**
+   * The table on which to insert.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * An array of fields on which to insert.
+   *
+   * @var array
+   */
+  protected $insertFields = array();
+
+  /**
+   * An array of fields that should be set to their database-defined defaults.
+   *
+   * @var array
+   */
+  protected $defaultFields = array();
+
+  /**
+   * A nested array of values to insert.
+   *
+   * $insertValues is an array of arrays. Each sub-array is either an
+   * associative array whose keys are field names and whose values are field
+   * values to insert, or a non-associative array of values in the same order
+   * as $insertFields.
+   *
+   * Whether multiple insert sets will be run in a single query or multiple
+   * queries is left to individual drivers to implement in whatever manner is
+   * most appropriate. The order of values in each sub-array must match the
+   * order of fields in $insertFields.
+   *
+   * @var array
+   */
+  protected $insertValues = array();
+
+  /**
+   * A SelectQuery object to fetch the rows that should be inserted.
+   *
+   * @var SelectQueryInterface
+   */
+  protected $fromQuery;
+
+  /**
+   * Constructs an Insert object.
+   *
+   * @param Drupal\Core\Database\Connection $connection
+   *   A DatabaseConnection object.
+   * @param string $table
+   *   Name of the table to associate with this query.
+   * @param array $options
+   *   Array of database options.
+   */
+  public function __construct($connection, $table, array $options = array()) {
+    if (!isset($options['return'])) {
+      $options['return'] = Database::RETURN_INSERT_ID;
+    }
+    parent::__construct($connection, $options);
+    $this->table = $table;
+  }
+
+  /**
+   * Adds a set of field->value pairs to be inserted.
+   *
+   * This method may only be called once. Calling it a second time will be
+   * ignored. To queue up multiple sets of values to be inserted at once,
+   * use the values() method.
+   *
+   * @param $fields
+   *   An array of fields on which to insert. This array may be indexed or
+   *   associative. If indexed, the array is taken to be the list of fields.
+   *   If associative, the keys of the array are taken to be the fields and
+   *   the values are taken to be corresponding values to insert. If a
+   *   $values argument is provided, $fields must be indexed.
+   * @param $values
+   *   An array of fields to insert into the database. The values must be
+   *   specified in the same order as the $fields array.
+   *
+   * @return Drupal\Core\Database\Query\Insert
+   *   The called object.
+   */
+  public function fields(array $fields, array $values = array()) {
+    if (empty($this->insertFields)) {
+      if (empty($values)) {
+        if (!is_numeric(key($fields))) {
+          $values = array_values($fields);
+          $fields = array_keys($fields);
+        }
+      }
+      $this->insertFields = $fields;
+      if (!empty($values)) {
+        $this->insertValues[] = $values;
+      }
+    }
+
+    return $this;
+  }
+
+  /**
+   * Adds another set of values to the query to be inserted.
+   *
+   * If $values is a numeric-keyed array, it will be assumed to be in the same
+   * order as the original fields() call. If it is associative, it may be
+   * in any order as long as the keys of the array match the names of the
+   * fields.
+   *
+   * @param $values
+   *   An array of values to add to the query.
+   *
+   * @return Drupal\Core\Database\Query\Insert
+   *   The called object.
+   */
+  public function values(array $values) {
+    if (is_numeric(key($values))) {
+      $this->insertValues[] = $values;
+    }
+    else {
+      // Reorder the submitted values to match the fields array.
+      foreach ($this->insertFields as $key) {
+        $insert_values[$key] = $values[$key];
+      }
+      // For consistency, the values array is always numerically indexed.
+      $this->insertValues[] = array_values($insert_values);
+    }
+    return $this;
+  }
+
+  /**
+   * Specifies fields for which the database defaults should be used.
+   *
+   * If you want to force a given field to use the database-defined default,
+   * not NULL or undefined, use this method to instruct the database to use
+   * default values explicitly. In most cases this will not be necessary
+   * unless you are inserting a row that is all default values, as you cannot
+   * specify no values in an INSERT query.
+   *
+   * Specifying a field both in fields() and in useDefaults() is an error
+   * and will not execute.
+   *
+   * @param $fields
+   *   An array of values for which to use the default values
+   *   specified in the table definition.
+   *
+   * @return Drupal\Core\Database\Query\Insert
+   *   The called object.
+   */
+  public function useDefaults(array $fields) {
+    $this->defaultFields = $fields;
+    return $this;
+  }
+
+  /**
+   * Sets the fromQuery on this InsertQuery object.
+   *
+   * @param SelectQueryInterface $query
+   *   The query to fetch the rows that should be inserted.
+   *
+   * @return InsertQuery
+   *   The called object.
+   */
+  public function from(SelectInterface $query) {
+    $this->fromQuery = $query;
+    return $this;
+  }
+
+  /**
+   * Executes the insert query.
+   *
+   * @return
+   *   The last insert ID of the query, if one exists. If the query
+   *   was given multiple sets of values to insert, the return value is
+   *   undefined. If no fields are specified, this method will do nothing and
+   *   return NULL. That makes it safe to use in multi-insert loops.
+   */
+  public function execute() {
+    // If validation fails, simply return NULL. Note that validation routines
+    // in preExecute() may throw exceptions instead.
+    if (!$this->preExecute()) {
+      return NULL;
+    }
+
+    // If we're selecting from a SelectQuery, finish building the query and
+    // pass it back, as any remaining options are irrelevant.
+    if (!empty($this->fromQuery)) {
+      $sql = (string) $this;
+      // The SelectQuery may contain arguments, load and pass them through.
+      return $this->connection->query($sql, $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
+    // databases, such as SQLite, this is also a notable performance boost.
+    $transaction = $this->connection->startTransaction();
+
+    try {
+      $sql = (string) $this;
+      foreach ($this->insertValues as $insert_values) {
+        $last_insert_id = $this->connection->query($sql, $insert_values, $this->queryOptions);
+      }
+    }
+    catch (Exception $e) {
+      // One of the INSERTs failed, rollback the whole batch.
+      $transaction->rollback();
+      // Rethrow the exception for the calling code.
+      throw $e;
+    }
+
+    // Re-initialize the values array so that we can re-use this query.
+    $this->insertValues = array();
+
+    // Transaction commits here where $transaction looses scope.
+
+    return $last_insert_id;
+  }
+
+  /**
+   * Implements PHP magic __toString method to convert the query to a string.
+   *
+   * @return string
+   *   The prepared statement.
+   */
+  public function __toString() {
+    // Create a sanitized comment string to prepend to the query.
+    $comments = $this->connection->makeComment($this->comments);
+
+    // Default fields are always placed first for consistency.
+    $insert_fields = array_merge($this->defaultFields, $this->insertFields);
+
+    if (!empty($this->fromQuery)) {
+      return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') ' . $this->fromQuery;
+    }
+
+    // For simplicity, we will use the $placeholders array to inject
+    // default keywords even though they are not, strictly speaking,
+    // placeholders for prepared statements.
+    $placeholders = array();
+    $placeholders = array_pad($placeholders, count($this->defaultFields), 'default');
+    $placeholders = array_pad($placeholders, count($this->insertFields), '?');
+
+    return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES (' . implode(', ', $placeholders) . ')';
+  }
+
+  /**
+   * Preprocesses and validates the query.
+   *
+   * @return
+   *   TRUE if the validation was successful, FALSE if not.
+   *
+   * @throws Drupal\Core\Database\Query\FieldsOverlapException
+   * @throws Drupal\Core\Database\Query\NoFieldsException
+   */
+  public function preExecute() {
+    // Confirm that the user did not try to specify an identical
+    // field and default field.
+    if (array_intersect($this->insertFields, $this->defaultFields)) {
+      throw new FieldsOverlapException('You may not specify the same field to have a value and a schema-default value.');
+    }
+
+    if (!empty($this->fromQuery)) {
+      // We have to assume that the used aliases match the insert fields.
+      // Regular fields are added to the query before expressions, maintain the
+      // same order for the insert fields.
+      // This behavior can be overridden by calling fields() manually as only the
+      // first call to fields() does have an effect.
+      $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) {
+      throw new NoFieldsException('There are no fields available to insert with.');
+    }
+
+    // If no values have been added, silently ignore this query. This can happen
+    // if values are added conditionally, so we don't want to throw an
+    // exception.
+    if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
+      return FALSE;
+    }
+    return TRUE;
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Query/InvalidMergeQueryException.php b/core/lib/Drupal/Core/Database/Query/InvalidMergeQueryException.php
new file mode 100644
index 0000000000000000000000000000000000000000..59ad1c9c3037e637b050c42d9b1fd87cc0364f13
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/InvalidMergeQueryException.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\InvalidMergeQueryException
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\DatabaseException;
+
+use InvalidArgumentException;
+
+/**
+ * Exception thrown for merge queries that do not make semantic sense.
+ *
+ * There are many ways that a merge query could be malformed.  They should all
+ * throw this exception and set an appropriately descriptive message.
+ */
+class InvalidMergeQueryException extends InvalidArgumentException implements DatabaseException {}
diff --git a/core/lib/Drupal/Core/Database/Query/Merge.php b/core/lib/Drupal/Core/Database/Query/Merge.php
new file mode 100644
index 0000000000000000000000000000000000000000..547a22323b2d90bfa52205378a7d0a0c22b4598c
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/Merge.php
@@ -0,0 +1,457 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\Merge
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection;
+
+use Exception;
+
+/**
+ * General class for an abstracted MERGE query operation.
+ *
+ * An ANSI SQL:2003 compatible database would run the following query:
+ *
+ * @code
+ * MERGE INTO table_name_1 USING table_name_2 ON (condition)
+ *   WHEN MATCHED THEN
+ *   UPDATE SET column1 = value1 [, column2 = value2 ...]
+ *   WHEN NOT MATCHED THEN
+ *   INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...
+ * @endcode
+ *
+ * Other databases (most notably MySQL, PostgreSQL and SQLite) will emulate
+ * this statement by running a SELECT and then INSERT or UPDATE.
+ *
+ * By default, the two table names are identical and they are passed into the
+ * the constructor. table_name_2 can be specified by the
+ * MergeQuery::conditionTable() method. It can be either a string or a
+ * subquery.
+ *
+ * The condition is built exactly like SelectQuery or UpdateQuery conditions,
+ * the UPDATE query part is built similarly like an UpdateQuery and finally the
+ * INSERT query part is built similarly like an InsertQuery. However, both
+ * UpdateQuery and InsertQuery has a fields method so
+ * MergeQuery::updateFields() and MergeQuery::insertFields() needs to be called
+ * instead. MergeQuery::fields() can also be called which calls both of these
+ * methods as the common case is to use the same column-value pairs for both
+ * INSERT and UPDATE. However, this is not mandatory. Another convinient
+ * wrapper is MergeQuery::key() which adds the same column-value pairs to the
+ * condition and the INSERT query part.
+ *
+ * Several methods (key(), fields(), insertFields()) can be called to set a
+ * key-value pair for the INSERT query part. Subsequent calls for the same
+ * fields override the earlier ones. The same is true for UPDATE and key(),
+ * fields() and updateFields().
+ */
+class Merge extends Query implements ConditionInterface {
+  /**
+   * Returned by execute() if an INSERT query has been executed.
+   */
+  const STATUS_INSERT = 1;
+
+  /**
+   * Returned by execute() if an UPDATE query has been executed.
+   */
+  const STATUS_UPDATE = 2;
+
+  /**
+   * The table to be used for INSERT and UPDATE.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * The table or subquery to be used for the condition.
+   */
+  protected $conditionTable;
+
+  /**
+   * An array of fields on which to insert.
+   *
+   * @var array
+   */
+  protected $insertFields = array();
+
+  /**
+   * An array of fields which should be set to their database-defined defaults.
+   *
+   * Used on INSERT.
+   *
+   * @var array
+   */
+  protected $defaultFields = array();
+
+  /**
+   * An array of values to be inserted.
+   *
+   * @var string
+   */
+  protected $insertValues = array();
+
+  /**
+   * An array of fields that will be updated.
+   *
+   * @var array
+   */
+  protected $updateFields = array();
+
+  /**
+   * Array of fields to update to an expression in case of a duplicate record.
+   *
+   * This variable is a nested array in the following format:
+   * @code
+   * <some field> => array(
+   *  'condition' => <condition to execute, as a string>,
+   *  'arguments' => <array of arguments for condition, or NULL for none>,
+   * );
+   * @endcode
+   *
+   * @var array
+   */
+  protected $expressionFields = array();
+
+  /**
+   * Flag indicating whether an UPDATE is necessary.
+   *
+   * @var boolean
+   */
+  protected $needsUpdate = FALSE;
+
+  /**
+  * Constructs a Merge object.
+  *
+  * @param Drupal\Core\Database\Connection $connection
+  *   A Drupal\Core\Database\Connection object.
+  * @param string $table
+  *   Name of the table to associate with this query.
+  * @param array $options
+  *   Array of database options.
+  */
+  public function __construct(Connection $connection, $table, array $options = array()) {
+    $options['return'] = Database::RETURN_AFFECTED;
+    parent::__construct($connection, $options);
+    $this->table = $table;
+    $this->conditionTable = $table;
+    $this->condition = new Condition('AND');
+  }
+
+  /**
+   * Sets the table or subquery to be used for the condition.
+   *
+   * @param $table
+   *   The table name or the subquery to be used. Use a Select query object to
+   *   pass in a subquery.
+   *
+   * @return Drupal\Core\Database\Query\Merge
+   *   The called object.
+   */
+  protected function conditionTable($table) {
+    $this->conditionTable = $table;
+    return $this;
+  }
+
+  /**
+   * Adds a set of field->value pairs to be updated.
+   *
+   * @param $fields
+   *   An associative array of fields to write into the database. The array keys
+   *   are the field names and the values are the values to which to set them.
+   *
+   * @return Drupal\Core\Database\Query\Merge
+   *   The called object.
+   */
+  public function updateFields(array $fields) {
+    $this->updateFields = $fields;
+    $this->needsUpdate = TRUE;
+    return $this;
+  }
+
+  /**
+   * Specifies fields to be updated as an expression.
+   *
+   * Expression fields are cases such as counter = counter + 1. This method
+   * takes precedence over MergeQuery::updateFields() and it's wrappers,
+   * MergeQuery::key() and MergeQuery::fields().
+   *
+   * @param $field
+   *   The field to set.
+   * @param $expression
+   *   The field will be set to the value of this expression. This parameter
+   *   may include named placeholders.
+   * @param $arguments
+   *   If specified, this is an array of key/value pairs for named placeholders
+   *   corresponding to the expression.
+   *
+   * @return Drupal\Core\Database\Query\Merge
+   *   The called object.
+   */
+  public function expression($field, $expression, array $arguments = NULL) {
+    $this->expressionFields[$field] = array(
+      'expression' => $expression,
+      'arguments' => $arguments,
+    );
+    $this->needsUpdate = TRUE;
+    return $this;
+  }
+
+  /**
+   * Adds a set of field->value pairs to be inserted.
+   *
+   * @param $fields
+   *   An array of fields on which to insert. This array may be indexed or
+   *   associative. If indexed, the array is taken to be the list of fields.
+   *   If associative, the keys of the array are taken to be the fields and
+   *   the values are taken to be corresponding values to insert. If a
+   *   $values argument is provided, $fields must be indexed.
+   * @param $values
+   *   An array of fields to insert into the database. The values must be
+   *   specified in the same order as the $fields array.
+   *
+   * @return Drupal\Core\Database\Query\Merge
+   *   The called object.
+   */
+  public function insertFields(array $fields, array $values = array()) {
+    if ($values) {
+      $fields = array_combine($fields, $values);
+    }
+    $this->insertFields = $fields;
+    return $this;
+  }
+
+  /**
+   * Specifies fields for which the database-defaults should be used.
+   *
+   * If you want to force a given field to use the database-defined default,
+   * not NULL or undefined, use this method to instruct the database to use
+   * default values explicitly. In most cases this will not be necessary
+   * unless you are inserting a row that is all default values, as you cannot
+   * specify no values in an INSERT query.
+   *
+   * Specifying a field both in fields() and in useDefaults() is an error
+   * and will not execute.
+   *
+   * @param $fields
+   *   An array of values for which to use the default values
+   *   specified in the table definition.
+   *
+   * @return Drupal\Core\Database\Query\Merge
+   *   The called object.
+   */
+  public function useDefaults(array $fields) {
+    $this->defaultFields = $fields;
+    return $this;
+  }
+
+  /**
+   * Sets common field-value pairs in the INSERT and UPDATE query parts.
+   *
+   * This method should only be called once. It may be called either
+   * with a single associative array or two indexed arrays. If called
+   * with an associative array, the keys are taken to be the fields
+   * and the values are taken to be the corresponding values to set.
+   * If called with two arrays, the first array is taken as the fields
+   * and the second array is taken as the corresponding values.
+   *
+   * @param $fields
+   *   An array of fields to insert, or an associative array of fields and
+   *   values. The keys of the array are taken to be the fields and the values
+   *   are taken to be corresponding values to insert.
+   * @param $values
+   *   An array of values to set into the database. The values must be
+   *   specified in the same order as the $fields array.
+   *
+   * @return Drupal\Core\Database\Query\Merge
+   *   The called object.
+   */
+  public function fields(array $fields, array $values = array()) {
+    if ($values) {
+      $fields = array_combine($fields, $values);
+    }
+    foreach ($fields as $key => $value) {
+      $this->insertFields[$key] = $value;
+      $this->updateFields[$key] = $value;
+    }
+    $this->needsUpdate = TRUE;
+    return $this;
+  }
+
+  /**
+   * Sets the key field(s) to be used as conditions for this query.
+   *
+   * This method should only be called once. It may be called either
+   * with a single associative array or two indexed arrays. If called
+   * with an associative array, the keys are taken to be the fields
+   * and the values are taken to be the corresponding values to set.
+   * If called with two arrays, the first array is taken as the fields
+   * and the second array is taken as the corresponding values.
+   *
+   * The fields are copied to the condition of the query and the INSERT part.
+   * If no other method is called, the UPDATE will become a no-op.
+   *
+   * @param $fields
+   *   An array of fields to set, or an associative array of fields and values.
+   * @param $values
+   *   An array of values to set into the database. The values must be
+   *   specified in the same order as the $fields array.
+   *
+   * @return Drupal\Core\Database\Query\Merge
+   *   The called object.
+   */
+  public function key(array $fields, array $values = array()) {
+    if ($values) {
+      $fields = array_combine($fields, $values);
+    }
+    foreach ($fields as $key => $value) {
+      $this->insertFields[$key] = $value;
+      $this->condition($key, $value);
+    }
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::condition().
+   */
+  public function condition($field, $value = NULL, $operator = NULL) {
+    $this->condition->condition($field, $value, $operator);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::isNull().
+   */
+  public function isNull($field) {
+    $this->condition->isNull($field);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::isNotNull().
+   */
+  public function isNotNull($field) {
+    $this->condition->isNotNull($field);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::exists().
+   */
+  public function exists(SelectInterface $select) {
+    $this->condition->exists($select);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::notExists().
+   */
+  public function notExists(SelectInterface $select) {
+    $this->condition->notExists($select);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::conditions().
+   */
+  public function &conditions() {
+    return $this->condition->conditions();
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::arguments().
+   */
+  public function arguments() {
+    return $this->condition->arguments();
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::where().
+   */
+  public function where($snippet, $args = array()) {
+    $this->condition->where($snippet, $args);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compile().
+   */
+  public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
+    return $this->condition->compile($connection, $queryPlaceholder);
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compiled().
+   */
+  public function compiled() {
+    return $this->condition->compiled();
+  }
+
+  /**
+   * Implements PHP magic __toString method to convert the query to a string.
+   *
+   * In the degenerate case, there is no string-able query as this operation
+   * is potentially two queries.
+   *
+   * @return string
+   *   The prepared query statement.
+   */
+  public function __toString() {
+  }
+
+  public function execute() {
+    // Wrap multiple queries in a transaction, if the database supports it.
+    $transaction = $this->connection->startTransaction();
+    try {
+      if (!count($this->condition)) {
+        throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
+      }
+      $select = $this->connection->select($this->conditionTable)
+        ->condition($this->condition)
+        ->forUpdate();
+      $select->addExpression('1');
+      if (!$select->execute()->fetchField()) {
+        try {
+          $insert = $this->connection->insert($this->table)->fields($this->insertFields);
+          if ($this->defaultFields) {
+            $insert->useDefaults($this->defaultFields);
+          }
+          $insert->execute();
+          return self::STATUS_INSERT;
+        }
+        catch (Exception $e) {
+          // The insert query failed, maybe it's because a racing insert query
+          // beat us in inserting the same row. Retry the select query, if it
+          // returns a row, ignore the error and continue with the update
+          // query below.
+          if (!$select->execute()->fetchField()) {
+            throw $e;
+          }
+        }
+      }
+      if ($this->needsUpdate) {
+        $update = $this->connection->update($this->table)
+          ->fields($this->updateFields)
+          ->condition($this->condition);
+        if ($this->expressionFields) {
+          foreach ($this->expressionFields as $field => $data) {
+            $update->expression($field, $data['expression'], $data['arguments']);
+          }
+        }
+        $update->execute();
+        return self::STATUS_UPDATE;
+      }
+    }
+    catch (Exception $e) {
+      // Something really wrong happened here, bubble up the exception to the
+      // caller.
+      $transaction->rollback();
+      throw $e;
+    }
+    // Transaction commits here where $transaction looses scope.
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Query/NoFieldsException.php b/core/lib/Drupal/Core/Database/Query/NoFieldsException.php
new file mode 100644
index 0000000000000000000000000000000000000000..18851fdce52151188d0f29e5b56ed82ad29e4ff0
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/NoFieldsException.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\NoFieldsException
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\DatabaseException;
+
+use InvalidArgumentException;
+
+/**
+ * Exception thrown if an insert query doesn't specify insert or default fields.
+ */
+class NoFieldsException extends InvalidArgumentException implements DatabaseException {}
diff --git a/core/lib/Drupal/Core/Database/Query/PlaceholderInterface.php b/core/lib/Drupal/Core/Database/Query/PlaceholderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..68b802e676cb9fdf5d0c9886bbeac492393f16dd
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/PlaceholderInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\PlaceholderInterface
+ */
+
+namespace Drupal\Core\Database\Query;
+
+/**
+ * Interface for a query that accepts placeholders.
+ */
+interface PlaceholderInterface {
+
+  /**
+   * Returns a unique identifier for this object.
+   */
+  public function uniqueIdentifier();
+
+  /**
+   * Returns the next placeholder ID for the query.
+   *
+   * @return
+   *   The next available placeholder ID as an integer.
+   */
+  public function nextPlaceholder();
+}
diff --git a/core/lib/Drupal/Core/Database/Query/Query.php b/core/lib/Drupal/Core/Database/Query/Query.php
new file mode 100644
index 0000000000000000000000000000000000000000..95ab4b9225dc2c5729ebafc7b47e40c5289408a9
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/Query.php
@@ -0,0 +1,180 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\Query
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection;
+
+/**
+ * Base class for query builders.
+ *
+ * Note that query builders use PHP's magic __toString() method to compile the
+ * query object into a prepared statement.
+ */
+abstract class Query implements PlaceholderInterface {
+
+  /**
+   * The connection object on which to run this query.
+   *
+   * @var Drupal\Core\Database\Connection
+   */
+  protected $connection;
+
+  /**
+   * The target of the connection object.
+   *
+   * @var string
+   */
+  protected $connectionTarget;
+
+  /**
+   * The key of the connection object.
+   *
+   * @var string
+   */
+  protected $connectionKey;
+
+  /**
+   * The query options to pass on to the connection object.
+   *
+   * @var array
+   */
+  protected $queryOptions;
+
+  /**
+   * A unique identifier for this query object.
+   */
+  protected $uniqueIdentifier;
+
+  /**
+   * The placeholder counter.
+   */
+  protected $nextPlaceholder = 0;
+
+  /**
+   * An array of comments that can be prepended to a query.
+   *
+   * @var array
+   */
+  protected $comments = array();
+
+  /**
+   * Constructs a Query object.
+   *
+   * @param Drupal\Core\Database\Connection $connection
+   *   Database connection object.
+   * @param array $options
+   *   Array of query options.
+   */
+  public function __construct(Connection $connection, $options) {
+    $this->uniqueIdentifier = uniqid('', TRUE);
+
+    $this->connection = $connection;
+    $this->connectionKey = $this->connection->getKey();
+    $this->connectionTarget = $this->connection->getTarget();
+
+    $this->queryOptions = $options;
+  }
+
+  /**
+   * Implements the magic __sleep function to disconnect from the database.
+   */
+  public function __sleep() {
+    $keys = get_object_vars($this);
+    unset($keys['connection']);
+    return array_keys($keys);
+  }
+
+  /**
+   * Implements the magic __wakeup function to reconnect to the database.
+   */
+  public function __wakeup() {
+    $this->connection = Database::getConnection($this->connectionTarget, $this->connectionKey);
+  }
+
+  /**
+   * Implements the magic __clone function.
+   */
+  public function __clone() {
+    $this->uniqueIdentifier = uniqid('', TRUE);
+  }
+
+  /**
+   * Runs the query against the database.
+   */
+  abstract protected function execute();
+
+  /**
+   * Implements PHP magic __toString method to convert the query to a string.
+   *
+   * The toString operation is how we compile a query object to a prepared
+   * statement.
+   *
+   * @return
+   *   A prepared statement query string for this object.
+   */
+  abstract public function __toString();
+
+  /**
+   * Returns a unique identifier for this object.
+   */
+  public function uniqueIdentifier() {
+    return $this->uniqueIdentifier;
+  }
+
+  /**
+   * Gets the next placeholder value for this query object.
+   *
+   * @return int
+   *   Next placeholder value.
+   */
+  public function nextPlaceholder() {
+    return $this->nextPlaceholder++;
+  }
+
+  /**
+   * Adds a comment to the query.
+   *
+   * By adding a comment to a query, you can more easily find it in your
+   * query log or the list of active queries on an SQL server. This allows
+   * for easier debugging and allows you to more easily find where a query
+   * with a performance problem is being generated.
+   *
+   * The comment string will be sanitized to remove * / and other characters
+   * that may terminate the string early so as to avoid SQL injection attacks.
+   *
+   * @param $comment
+   *   The comment string to be inserted into the query.
+   *
+   * @return Drupal\Core\Database\Query\Query
+   *   The called object.
+   */
+  public function comment($comment) {
+    $this->comments[] = $comment;
+    return $this;
+  }
+
+  /**
+   * Returns a reference to the comments array for the query.
+   *
+   * Because this method returns by reference, alter hooks may edit the comments
+   * array directly to make their changes. If just adding comments, however, the
+   * use of comment() is preferred.
+   *
+   * Note that this method must be called by reference as well:
+   * @code
+   * $comments =& $query->getComments();
+   * @endcode
+   *
+   * @return
+   *   A reference to the comments array structure.
+   */
+  public function &getComments() {
+    return $this->comments;
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php
new file mode 100644
index 0000000000000000000000000000000000000000..2d3159c36e7bde7c0ed981ac7e334283057343fe
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/Select.php
@@ -0,0 +1,765 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\Select
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection;
+
+
+/**
+ * Query builder for SELECT statements.
+ */
+class Select extends Query implements SelectInterface {
+
+  /**
+   * The fields to SELECT.
+   *
+   * @var array
+   */
+  protected $fields = array();
+
+  /**
+   * The expressions to SELECT as virtual fields.
+   *
+   * @var array
+   */
+  protected $expressions = array();
+
+  /**
+   * The tables against which to JOIN.
+   *
+   * This property is a nested array. Each entry is an array representing
+   * a single table against which to join. The structure of each entry is:
+   *
+   * array(
+   *   'type' => $join_type (one of INNER, LEFT OUTER, RIGHT OUTER),
+   *   'table' => $table,
+   *   'alias' => $alias_of_the_table,
+   *   'condition' => $condition_clause_on_which_to_join,
+   *   'arguments' => $array_of_arguments_for_placeholders_in_the condition.
+   *   'all_fields' => TRUE to SELECT $alias.*, FALSE or NULL otherwise.
+   * )
+   *
+   * If $table is a string, it is taken as the name of a table. If it is
+   * a Select query object, it is taken as a subquery.
+   *
+   * @var array
+   */
+  protected $tables = array();
+
+  /**
+   * The fields by which to order this query.
+   *
+   * This is an associative array. The keys are the fields to order, and the value
+   * is the direction to order, either ASC or DESC.
+   *
+   * @var array
+   */
+  protected $order = array();
+
+  /**
+   * The fields by which to group.
+   *
+   * @var array
+   */
+  protected $group = array();
+
+  /**
+   * The conditional object for the WHERE clause.
+   *
+   * @var Drupal\Core\Database\Query\Condition
+   */
+  protected $where;
+
+  /**
+   * The conditional object for the HAVING clause.
+   *
+   * @var Drupal\Core\Database\Query\Condition
+   */
+  protected $having;
+
+  /**
+   * Whether or not this query should be DISTINCT
+   *
+   * @var boolean
+   */
+  protected $distinct = FALSE;
+
+  /**
+   * The range limiters for this query.
+   *
+   * @var array
+   */
+  protected $range;
+
+  /**
+   * An array whose elements specify a query to UNION, and the UNION type. The
+   * 'type' key may be '', 'ALL', or 'DISTINCT' to represent a 'UNION',
+   * 'UNION ALL', or 'UNION DISTINCT' statement, respectively.
+   *
+   * All entries in this array will be applied from front to back, with the
+   * first query to union on the right of the original query, the second union
+   * to the right of the first, etc.
+   *
+   * @var array
+   */
+  protected $union = array();
+
+  /**
+   * Indicates if preExecute() has already been called.
+   * @var boolean
+   */
+  protected $prepared = FALSE;
+
+  /**
+   * The FOR UPDATE status
+   */
+  protected $forUpdate = FALSE;
+
+  public function __construct($table, $alias = NULL, Connection $connection, $options = array()) {
+    $options['return'] = Database::RETURN_STATEMENT;
+    parent::__construct($connection, $options);
+    $this->where = new Condition('AND');
+    $this->having = new Condition('AND');
+    $this->addJoin(NULL, $table, $alias);
+  }
+
+  /* Implementations of Drupal\Core\Database\Query\AlterableInterface. */
+
+  public function addTag($tag) {
+    $this->alterTags[$tag] = 1;
+    return $this;
+  }
+
+  public function hasTag($tag) {
+    return isset($this->alterTags[$tag]);
+  }
+
+  public function hasAllTags() {
+    return !(boolean)array_diff(func_get_args(), array_keys($this->alterTags));
+  }
+
+  public function hasAnyTag() {
+    return (boolean)array_intersect(func_get_args(), array_keys($this->alterTags));
+  }
+
+  public function addMetaData($key, $object) {
+    $this->alterMetaData[$key] = $object;
+    return $this;
+  }
+
+  public function getMetaData($key) {
+    return isset($this->alterMetaData[$key]) ? $this->alterMetaData[$key] : NULL;
+  }
+
+  /* Implementations of Drupal\Core\Database\Query\ConditionInterface for the WHERE clause. */
+
+  public function condition($field, $value = NULL, $operator = NULL) {
+    $this->where->condition($field, $value, $operator);
+    return $this;
+  }
+
+  public function &conditions() {
+    return $this->where->conditions();
+  }
+
+  public function arguments() {
+    if (!$this->compiled()) {
+      return NULL;
+    }
+
+    $args = $this->where->arguments() + $this->having->arguments();
+
+    foreach ($this->tables as $table) {
+      if ($table['arguments']) {
+        $args += $table['arguments'];
+      }
+      // If this table is a subquery, grab its arguments recursively.
+      if ($table['table'] instanceof SelectInterface) {
+        $args += $table['table']->arguments();
+      }
+    }
+
+    foreach ($this->expressions as $expression) {
+      if ($expression['arguments']) {
+        $args += $expression['arguments'];
+      }
+    }
+
+    // If there are any dependent queries to UNION,
+    // incorporate their arguments recursively.
+    foreach ($this->union as $union) {
+      $args += $union['query']->arguments();
+    }
+
+    return $args;
+  }
+
+  public function where($snippet, $args = array()) {
+    $this->where->where($snippet, $args);
+    return $this;
+  }
+
+  public function isNull($field) {
+    $this->where->isNull($field);
+    return $this;
+  }
+
+  public function isNotNull($field) {
+    $this->where->isNotNull($field);
+    return $this;
+  }
+
+  public function exists(SelectInterface $select) {
+    $this->where->exists($select);
+    return $this;
+  }
+
+  public function notExists(SelectInterface $select) {
+    $this->where->notExists($select);
+    return $this;
+  }
+
+  public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
+    $this->where->compile($connection, $queryPlaceholder);
+    $this->having->compile($connection, $queryPlaceholder);
+
+    foreach ($this->tables as $table) {
+      // If this table is a subquery, compile it recursively.
+      if ($table['table'] instanceof SelectInterface) {
+        $table['table']->compile($connection, $queryPlaceholder);
+      }
+    }
+
+    // If there are any dependent queries to UNION, compile it recursively.
+    foreach ($this->union as $union) {
+      $union['query']->compile($connection, $queryPlaceholder);
+    }
+  }
+
+  public function compiled() {
+    if (!$this->where->compiled() || !$this->having->compiled()) {
+      return FALSE;
+    }
+
+    foreach ($this->tables as $table) {
+      // If this table is a subquery, check its status recursively.
+      if ($table['table'] instanceof SelectInterface) {
+        if (!$table['table']->compiled()) {
+          return FALSE;
+        }
+      }
+    }
+
+    foreach ($this->union as $union) {
+      if (!$union['query']->compiled()) {
+        return FALSE;
+      }
+    }
+
+    return TRUE;
+  }
+
+  /* Implementations of Drupal\Core\Database\Query\ConditionInterface for the HAVING clause. */
+
+  public function havingCondition($field, $value = NULL, $operator = NULL) {
+    $this->having->condition($field, $value, $operator);
+    return $this;
+  }
+
+  public function &havingConditions() {
+    return $this->having->conditions();
+  }
+
+  public function havingArguments() {
+    return $this->having->arguments();
+  }
+
+  public function having($snippet, $args = array()) {
+    $this->having->where($snippet, $args);
+    return $this;
+  }
+
+  public function havingCompile(Connection $connection) {
+    return $this->having->compile($connection, $this);
+  }
+
+  /* Implementations of Drupal\Core\Database\Query\ExtendableInterface. */
+
+  public function extend($extender_name) {
+    $override_class = $extender_name . '_' . $this->connection->driver();
+    if (class_exists($override_class)) {
+      $extender_name = $override_class;
+    }
+    return new $extender_name($this, $this->connection);
+  }
+
+  public function havingIsNull($field) {
+    $this->having->isNull($field);
+    return $this;
+  }
+
+  public function havingIsNotNull($field) {
+    $this->having->isNotNull($field);
+    return $this;
+  }
+
+  public function havingExists(SelectInterface $select) {
+    $this->having->exists($select);
+    return $this;
+  }
+
+  public function havingNotExists(SelectInterface $select) {
+    $this->having->notExists($select);
+    return $this;
+  }
+
+  public function forUpdate($set = TRUE) {
+    if (isset($set)) {
+      $this->forUpdate = $set;
+    }
+    return $this;
+  }
+
+  /* Alter accessors to expose the query data to alter hooks. */
+
+  public function &getFields() {
+    return $this->fields;
+  }
+
+  public function &getExpressions() {
+    return $this->expressions;
+  }
+
+  public function &getOrderBy() {
+    return $this->order;
+  }
+
+  public function &getGroupBy() {
+    return $this->group;
+  }
+
+  public function &getTables() {
+    return $this->tables;
+  }
+
+  public function &getUnion() {
+    return $this->union;
+  }
+
+  public function getArguments(PlaceholderInterface $queryPlaceholder = NULL) {
+    if (!isset($queryPlaceholder)) {
+      $queryPlaceholder = $this;
+    }
+    $this->compile($this->connection, $queryPlaceholder);
+    return $this->arguments();
+  }
+
+  /**
+   * Indicates if preExecute() has already been called on that object.
+   */
+  public function isPrepared() {
+    return $this->prepared;
+  }
+
+  /**
+   * Generic preparation and validation for a SELECT query.
+   *
+   * @return
+   *   TRUE if the validation was successful, FALSE if not.
+   */
+  public function preExecute(SelectInterface $query = NULL) {
+    // If no query object is passed in, use $this.
+    if (!isset($query)) {
+      $query = $this;
+    }
+
+    // Only execute this once.
+    if ($query->isPrepared()) {
+      return TRUE;
+    }
+
+    // Modules may alter all queries or only those having a particular tag.
+    if (isset($this->alterTags)) {
+      $hooks = array('query');
+      foreach ($this->alterTags as $tag => $value) {
+        $hooks[] = 'query_' . $tag;
+      }
+      drupal_alter($hooks, $query);
+    }
+
+    $this->prepared = TRUE;
+
+    // Now also prepare any sub-queries.
+    foreach ($this->tables as $table) {
+      if ($table['table'] instanceof SelectInterface) {
+        $table['table']->preExecute();
+      }
+    }
+
+    foreach ($this->union as $union) {
+      $union['query']->preExecute();
+    }
+
+    return $this->prepared;
+  }
+
+  public function execute() {
+    // If validation fails, simply return NULL.
+    // Note that validation routines in preExecute() may throw exceptions instead.
+    if (!$this->preExecute()) {
+      return NULL;
+    }
+
+    $args = $this->getArguments();
+    return $this->connection->query((string) $this, $args, $this->queryOptions);
+  }
+
+  public function distinct($distinct = TRUE) {
+    $this->distinct = $distinct;
+    return $this;
+  }
+
+  public function addField($table_alias, $field, $alias = NULL) {
+    // If no alias is specified, first try the field name itself.
+    if (empty($alias)) {
+      $alias = $field;
+    }
+
+    // If that's already in use, try the table name and field name.
+    if (!empty($this->fields[$alias])) {
+      $alias = $table_alias . '_' . $field;
+    }
+
+    // If that is already used, just add a counter until we find an unused alias.
+    $alias_candidate = $alias;
+    $count = 2;
+    while (!empty($this->fields[$alias_candidate])) {
+      $alias_candidate = $alias . '_' . $count++;
+    }
+    $alias = $alias_candidate;
+
+    $this->fields[$alias] = array(
+      'field' => $field,
+      'table' => $table_alias,
+      'alias' => $alias,
+    );
+
+    return $alias;
+  }
+
+  public function fields($table_alias, array $fields = array()) {
+
+    if ($fields) {
+      foreach ($fields as $field) {
+        // We don't care what alias was assigned.
+        $this->addField($table_alias, $field);
+      }
+    }
+    else {
+      // We want all fields from this table.
+      $this->tables[$table_alias]['all_fields'] = TRUE;
+    }
+
+    return $this;
+  }
+
+  public function addExpression($expression, $alias = NULL, $arguments = array()) {
+    if (empty($alias)) {
+      $alias = 'expression';
+    }
+
+    $alias_candidate = $alias;
+    $count = 2;
+    while (!empty($this->expressions[$alias_candidate])) {
+      $alias_candidate = $alias . '_' . $count++;
+    }
+    $alias = $alias_candidate;
+
+    $this->expressions[$alias] = array(
+      'expression' => $expression,
+      'alias' => $alias,
+      'arguments' => $arguments,
+    );
+
+    return $alias;
+  }
+
+  public function join($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->addJoin('INNER', $table, $alias, $condition, $arguments);
+  }
+
+  public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->addJoin('INNER', $table, $alias, $condition, $arguments);
+  }
+
+  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->addJoin('LEFT OUTER', $table, $alias, $condition, $arguments);
+  }
+
+  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->addJoin('RIGHT OUTER', $table, $alias, $condition, $arguments);
+  }
+
+  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array()) {
+
+    if (empty($alias)) {
+      if ($table instanceof SelectInterface) {
+        $alias = 'subquery';
+      }
+      else {
+        $alias = $table;
+      }
+    }
+
+    $alias_candidate = $alias;
+    $count = 2;
+    while (!empty($this->tables[$alias_candidate])) {
+      $alias_candidate = $alias . '_' . $count++;
+    }
+    $alias = $alias_candidate;
+
+    if (is_string($condition)) {
+      $condition = str_replace('%alias', $alias, $condition);
+    }
+
+    $this->tables[$alias] = array(
+      'join type' => $type,
+      'table' => $table,
+      'alias' => $alias,
+      'condition' => $condition,
+      'arguments' => $arguments,
+    );
+
+    return $alias;
+  }
+
+  public function orderBy($field, $direction = 'ASC') {
+    $this->order[$field] = $direction;
+    return $this;
+  }
+
+  public function orderRandom() {
+    $alias = $this->addExpression('RAND()', 'random_field');
+    $this->orderBy($alias);
+    return $this;
+  }
+
+  public function range($start = NULL, $length = NULL) {
+    $this->range = func_num_args() ? array('start' => $start, 'length' => $length) : array();
+    return $this;
+  }
+
+  public function union(SelectInterface $query, $type = '') {
+    // Handle UNION aliasing.
+    switch ($type) {
+      // Fold UNION DISTINCT to UNION for better cross database support.
+      case 'DISTINCT':
+      case '':
+        $type = 'UNION';
+        break;
+
+      case 'ALL':
+        $type = 'UNION ALL';
+      default:
+    }
+
+    $this->union[] = array(
+      'type' => $type,
+      'query' => $query,
+    );
+
+    return $this;
+  }
+
+  public function groupBy($field) {
+    $this->group[$field] = $field;
+    return $this;
+  }
+
+  public function countQuery() {
+    // Create our new query object that we will mutate into a count query.
+    $count = clone($this);
+
+    $group_by = $count->getGroupBy();
+    $having = $count->havingConditions();
+
+    if (!$count->distinct && !isset($having[0])) {
+      // When not executing a distinct query, we can zero-out existing fields
+      // and expressions that are not used by a GROUP BY or HAVING. Fields
+      // listed in a GROUP BY or HAVING clause need to be present in the
+      // query.
+      $fields =& $count->getFields();
+      foreach (array_keys($fields) as $field) {
+        if (empty($group_by[$field])) {
+          unset($fields[$field]);
+        }
+      }
+
+      $expressions =& $count->getExpressions();
+      foreach (array_keys($expressions) as $field) {
+        if (empty($group_by[$field])) {
+          unset($expressions[$field]);
+        }
+      }
+
+      // Also remove 'all_fields' statements, which are expanded into tablename.*
+      // when the query is executed.
+      foreach ($count->tables as $alias => &$table) {
+        unset($table['all_fields']);
+      }
+    }
+
+    // If we've just removed all fields from the query, make sure there is at
+    // least one so that the query still runs.
+    $count->addExpression('1');
+
+    // Ordering a count query is a waste of cycles, and breaks on some
+    // databases anyway.
+    $orders = &$count->getOrderBy();
+    $orders = array();
+
+    if ($count->distinct && !empty($group_by)) {
+      // If the query is distinct and contains a GROUP BY, we need to remove the
+      // distinct because SQL99 does not support counting on distinct multiple fields.
+      $count->distinct = FALSE;
+    }
+
+    $query = $this->connection->select($count);
+    $query->addExpression('COUNT(*)');
+
+    return $query;
+  }
+
+  public function __toString() {
+    // For convenience, we compile the query ourselves if the caller forgot
+    // to do it. This allows constructs like "(string) $query" to work. When
+    // the query will be executed, it will be recompiled using the proper
+    // placeholder generator anyway.
+    if (!$this->compiled()) {
+      $this->compile($this->connection, $this);
+    }
+
+    // Create a sanitized comment string to prepend to the query.
+    $comments = $this->connection->makeComment($this->comments);
+
+    // SELECT
+    $query = $comments . 'SELECT ';
+    if ($this->distinct) {
+      $query .= 'DISTINCT ';
+    }
+
+    // FIELDS and EXPRESSIONS
+    $fields = array();
+    foreach ($this->tables as $alias => $table) {
+      if (!empty($table['all_fields'])) {
+        $fields[] = $this->connection->escapeTable($alias) . '.*';
+      }
+    }
+    foreach ($this->fields as $alias => $field) {
+      // Always use the AS keyword for field aliases, as some
+      // databases require it (e.g., PostgreSQL).
+      $fields[] = (isset($field['table']) ? $this->connection->escapeTable($field['table']) . '.' : '') . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']);
+    }
+    foreach ($this->expressions as $alias => $expression) {
+      $fields[] = $expression['expression'] . ' AS ' . $this->connection->escapeAlias($expression['alias']);
+    }
+    $query .= implode(', ', $fields);
+
+
+    // FROM - We presume all queries have a FROM, as any query that doesn't won't need the query builder anyway.
+    $query .= "\nFROM ";
+    foreach ($this->tables as $alias => $table) {
+      $query .= "\n";
+      if (isset($table['join type'])) {
+        $query .= $table['join type'] . ' JOIN ';
+      }
+
+      // If the table is a subquery, compile it and integrate it into this query.
+      if ($table['table'] instanceof SelectInterface) {
+        // Run preparation steps on this sub-query before converting to string.
+        $subquery = $table['table'];
+        $subquery->preExecute();
+        $table_string = '(' . (string) $subquery . ')';
+      }
+      else {
+        $table_string = '{' . $this->connection->escapeTable($table['table']) . '}';
+      }
+
+      // Don't use the AS keyword for table aliases, as some
+      // databases don't support it (e.g., Oracle).
+      $query .=  $table_string . ' ' . $this->connection->escapeTable($table['alias']);
+
+      if (!empty($table['condition'])) {
+        $query .= ' ON ' . $table['condition'];
+      }
+    }
+
+    // WHERE
+    if (count($this->where)) {
+      // There is an implicit string cast on $this->condition.
+      $query .= "\nWHERE " . $this->where;
+    }
+
+    // GROUP BY
+    if ($this->group) {
+      $query .= "\nGROUP BY " . implode(', ', $this->group);
+    }
+
+    // HAVING
+    if (count($this->having)) {
+      // There is an implicit string cast on $this->having.
+      $query .= "\nHAVING " . $this->having;
+    }
+
+    // ORDER BY
+    if ($this->order) {
+      $query .= "\nORDER BY ";
+      $fields = array();
+      foreach ($this->order as $field => $direction) {
+        $fields[] = $field . ' ' . $direction;
+      }
+      $query .= implode(', ', $fields);
+    }
+
+    // RANGE
+    // There is no universal SQL standard for handling range or limit clauses.
+    // Fortunately, all core-supported databases use the same range syntax.
+    // Databases that need a different syntax can override this method and
+    // do whatever alternate logic they need to.
+    if (!empty($this->range)) {
+      $query .= "\nLIMIT " . (int) $this->range['length'] . " OFFSET " . (int) $this->range['start'];
+    }
+
+    // UNION is a little odd, as the select queries to combine are passed into
+    // this query, but syntactically they all end up on the same level.
+    if ($this->union) {
+      foreach ($this->union as $union) {
+        $query .= ' ' . $union['type'] . ' ' . (string) $union['query'];
+      }
+    }
+
+    if ($this->forUpdate) {
+      $query .= ' FOR UPDATE';
+    }
+
+    return $query;
+  }
+
+  public function __clone() {
+    // On cloning, also clone the dependent objects. However, we do not
+    // want to clone the database connection object as that would duplicate the
+    // connection itself.
+
+    $this->where = clone($this->where);
+    $this->having = clone($this->having);
+    foreach ($this->union as $key => $aggregate) {
+      $this->union[$key]['query'] = clone($aggregate['query']);
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Query/SelectExtender.php b/core/lib/Drupal/Core/Database/Query/SelectExtender.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f27d1b4b3b156a831af95c5cf2210b771ee053a
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/SelectExtender.php
@@ -0,0 +1,330 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\SelectExtender
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Connection;
+
+/**
+ * The base extender class for Select queries.
+ */
+class SelectExtender implements SelectInterface {
+
+  /**
+   * The Select query object we are extending/decorating.
+   *
+   * @var Drupal\Core\Database\Query\SelectInterface
+   */
+  protected $query;
+
+  /**
+   * The connection object on which to run this query.
+   *
+   * @var DatabaseConnection
+   */
+  protected $connection;
+
+  /**
+   * A unique identifier for this query object.
+   */
+  protected $uniqueIdentifier;
+
+  /**
+   * The placeholder counter.
+   */
+  protected $placeholder = 0;
+
+  public function __construct(SelectInterface $query, Connection $connection) {
+    $this->uniqueIdentifier = uniqid('', TRUE);
+    $this->query = $query;
+    $this->connection = $connection;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\PlaceholderInterface::uniqueIdentifier().
+   */
+  public function uniqueIdentifier() {
+    return $this->uniqueIdentifier;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\PlaceholderInterface::nextPlaceholder().
+   */
+  public function nextPlaceholder() {
+    return $this->placeholder++;
+  }
+
+  /* Implementations of Drupal\Core\Database\Query\AlterableInterface. */
+
+  public function addTag($tag) {
+    $this->query->addTag($tag);
+    return $this;
+  }
+
+  public function hasTag($tag) {
+    return $this->query->hasTag($tag);
+  }
+
+  public function hasAllTags() {
+    return call_user_func_array(array($this->query, 'hasAllTags'), func_get_args());
+  }
+
+  public function hasAnyTag() {
+    return call_user_func_array(array($this->query, 'hasAnyTags'), func_get_args());
+  }
+
+  public function addMetaData($key, $object) {
+    $this->query->addMetaData($key, $object);
+    return $this;
+  }
+
+  public function getMetaData($key) {
+    return $this->query->getMetaData($key);
+  }
+
+  /* Implementations of Drupal\Core\Database\Query\ConditionInterface for the WHERE clause. */
+
+  public function condition($field, $value = NULL, $operator = NULL) {
+    $this->query->condition($field, $value, $operator);
+    return $this;
+  }
+
+  public function &conditions() {
+    return $this->query->conditions();
+  }
+
+  public function arguments() {
+    return $this->query->arguments();
+  }
+
+  public function where($snippet, $args = array()) {
+    $this->query->where($snippet, $args);
+    return $this;
+  }
+
+  public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
+    return $this->query->compile($connection, $queryPlaceholder);
+  }
+
+  public function compiled() {
+    return $this->query->compiled();
+  }
+
+  /* Implementations of Drupal\Core\Database\Query\ConditionInterface for the HAVING clause. */
+
+  public function havingCondition($field, $value = NULL, $operator = '=') {
+    $this->query->havingCondition($field, $value, $operator);
+    return $this;
+  }
+
+  public function &havingConditions() {
+    return $this->query->havingConditions();
+  }
+
+  public function havingArguments() {
+    return $this->query->havingArguments();
+  }
+
+  public function having($snippet, $args = array()) {
+    $this->query->having($snippet, $args);
+    return $this;
+  }
+
+  public function havingCompile(Connection $connection) {
+    return $this->query->havingCompile($connection);
+  }
+
+  /* Implementations of Drupal\Core\Database\Query\ExtendableInterface. */
+
+  public function extend($extender_name) {
+    $class = $this->connection->getDriverClass($extender_name);
+    return new $class($this, $this->connection);
+  }
+
+  /* Alter accessors to expose the query data to alter hooks. */
+
+  public function &getFields() {
+    return $this->query->getFields();
+  }
+
+  public function &getExpressions() {
+    return $this->query->getExpressions();
+  }
+
+  public function &getOrderBy() {
+    return $this->query->getOrderBy();
+  }
+
+  public function &getGroupBy() {
+    return $this->query->getGroupBy();
+  }
+
+  public function &getTables() {
+    return $this->query->getTables();
+  }
+
+  public function &getUnion() {
+    return $this->query->getUnion();
+  }
+
+  public function getArguments(PlaceholderInterface $queryPlaceholder = NULL) {
+    return $this->query->getArguments($queryPlaceholder);
+  }
+
+  public function isPrepared() {
+    return $this->query->isPrepared();
+  }
+
+  public function preExecute(SelectInterface $query = NULL) {
+    // If no query object is passed in, use $this.
+    if (!isset($query)) {
+      $query = $this;
+    }
+
+    return $this->query->preExecute($query);
+  }
+
+  public function execute() {
+    // By calling preExecute() here, we force it to preprocess the extender
+    // object rather than just the base query object.  That means
+    // hook_query_alter() gets access to the extended object.
+    if (!$this->preExecute($this)) {
+      return NULL;
+    }
+
+    return $this->query->execute();
+  }
+
+  public function distinct($distinct = TRUE) {
+    $this->query->distinct($distinct);
+    return $this;
+  }
+
+  public function addField($table_alias, $field, $alias = NULL) {
+    return $this->query->addField($table_alias, $field, $alias);
+  }
+
+  public function fields($table_alias, array $fields = array()) {
+    $this->query->fields($table_alias, $fields);
+    return $this;
+  }
+
+  public function addExpression($expression, $alias = NULL, $arguments = array()) {
+    return $this->query->addExpression($expression, $alias, $arguments);
+  }
+
+  public function join($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->query->join($table, $alias, $condition, $arguments);
+  }
+
+  public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->query->innerJoin($table, $alias, $condition, $arguments);
+  }
+
+  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->query->leftJoin($table, $alias, $condition, $arguments);
+  }
+
+  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->query->rightJoin($table, $alias, $condition, $arguments);
+  }
+
+  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->query->addJoin($type, $table, $alias, $condition, $arguments);
+  }
+
+  public function orderBy($field, $direction = 'ASC') {
+    $this->query->orderBy($field, $direction);
+    return $this;
+  }
+
+  public function orderRandom() {
+    $this->query->orderRandom();
+    return $this;
+  }
+
+  public function range($start = NULL, $length = NULL) {
+    $this->query->range($start, $length);
+    return $this;
+  }
+
+  public function union(SelectInterface $query, $type = '') {
+    $this->query->union($query, $type);
+    return $this;
+  }
+
+  public function groupBy($field) {
+    $this->query->groupBy($field);
+    return $this;
+  }
+
+  public function forUpdate($set = TRUE) {
+    $this->query->forUpdate($set);
+    return $this;
+  }
+
+  public function countQuery() {
+    return $this->query->countQuery();
+  }
+
+  function isNull($field) {
+    $this->query->isNull($field);
+    return $this;
+  }
+
+  function isNotNull($field) {
+    $this->query->isNotNull($field);
+    return $this;
+  }
+
+  public function exists(SelectInterface $select) {
+    $this->query->exists($select);
+    return $this;
+  }
+
+  public function notExists(SelectInterface $select) {
+    $this->query->notExists($select);
+    return $this;
+  }
+
+  public function __toString() {
+    return (string) $this->query;
+  }
+
+  public function __clone() {
+    $this->uniqueIdentifier = uniqid('', TRUE);
+
+    // We need to deep-clone the query we're wrapping, which in turn may
+    // deep-clone other objects.  Exciting!
+    $this->query = clone($this->query);
+  }
+
+  /**
+   * Magic override for undefined methods.
+   *
+   * If one extender extends another extender, then methods in the inner extender
+   * will not be exposed on the outer extender.  That's because we cannot know
+   * in advance what those methods will be, so we cannot provide wrapping
+   * implementations as we do above.  Instead, we use this slower catch-all method
+   * to handle any additional methods.
+   */
+  public function __call($method, $args) {
+    $return = call_user_func_array(array($this->query, $method), $args);
+
+    // Some methods will return the called object as part of a fluent interface.
+    // Others will return some useful value.  If it's a value, then the caller
+    // probably wants that value.  If it's the called object, then we instead
+    // return this object.  That way we don't "lose" an extender layer when
+    // chaining methods together.
+    if ($return instanceof SelectInterface) {
+      return $this;
+    }
+    else {
+      return $return;
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Query/SelectInterface.php b/core/lib/Drupal/Core/Database/Query/SelectInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..779e69d2f74f397d5b703b1d4dacf181a0c57013
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/SelectInterface.php
@@ -0,0 +1,504 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\SelectInterface
+ */
+
+namespace Drupal\Core\Database\Query;
+
+/**
+ * Interface definition for a Select Query object.
+ */
+interface SelectInterface extends ConditionInterface, AlterableInterface, ExtendableInterface, PlaceholderInterface {
+
+  /* Alter accessors to expose the query data to alter hooks. */
+
+  /**
+   * Returns a reference to the fields array for this query.
+   *
+   * Because this method returns by reference, alter hooks may edit the fields
+   * array directly to make their changes. If just adding fields, however, the
+   * use of addField() is preferred.
+   *
+   * Note that this method must be called by reference as well:
+   *
+   * @code
+   * $fields =& $query->getFields();
+   * @endcode
+   *
+   * @return
+   *   A reference to the fields array structure.
+   */
+  public function &getFields();
+
+  /**
+   * Returns a reference to the expressions array for this query.
+   *
+   * Because this method returns by reference, alter hooks may edit the expressions
+   * array directly to make their changes. If just adding expressions, however, the
+   * use of addExpression() is preferred.
+   *
+   * Note that this method must be called by reference as well:
+   *
+   * @code
+   * $fields =& $query->getExpressions();
+   * @endcode
+   *
+   * @return
+   *   A reference to the expression array structure.
+   */
+  public function &getExpressions();
+
+  /**
+   * Returns a reference to the order by array for this query.
+   *
+   * Because this method returns by reference, alter hooks may edit the order-by
+   * array directly to make their changes. If just adding additional ordering
+   * fields, however, the use of orderBy() is preferred.
+   *
+   * Note that this method must be called by reference as well:
+   *
+   * @code
+   * $fields =& $query->getOrderBy();
+   * @endcode
+   *
+   * @return
+   *   A reference to the expression array structure.
+   */
+  public function &getOrderBy();
+
+  /**
+   * Returns a reference to the group-by array for this query.
+   *
+   * Because this method returns by reference, alter hooks may edit the group-by
+   * array directly to make their changes. If just adding additional grouping
+   * fields, however, the use of groupBy() is preferred.
+   *
+   * Note that this method must be called by reference as well:
+   *
+   * @code
+   * $fields =& $query->getGroupBy();
+   * @endcode
+   *
+   * @return
+   *   A reference to the group-by array structure.
+   */
+  public function &getGroupBy();
+
+  /**
+   * Returns a reference to the tables array for this query.
+   *
+   * Because this method returns by reference, alter hooks may edit the tables
+   * array directly to make their changes. If just adding tables, however, the
+   * use of the join() methods is preferred.
+   *
+   * Note that this method must be called by reference as well:
+   *
+   * @code
+   * $fields =& $query->getTables();
+   * @endcode
+   *
+   * @return
+   *   A reference to the tables array structure.
+   */
+  public function &getTables();
+
+  /**
+   * Returns a reference to the union queries for this query. This include
+   * queries for UNION, UNION ALL, and UNION DISTINCT.
+   *
+   * Because this method returns by reference, alter hooks may edit the tables
+   * array directly to make their changes. If just adding union queries,
+   * however, the use of the union() method is preferred.
+   *
+   * Note that this method must be called by reference as well:
+   *
+   * @code
+   * $fields =& $query->getUnion();
+   * @endcode
+   *
+   * @return
+   *   A reference to the union query array structure.
+   */
+  public function &getUnion();
+
+  /**
+   * Compiles and returns an associative array of the arguments for this prepared statement.
+   *
+   * @param $queryPlaceholder
+   *   When collecting the arguments of a subquery, the main placeholder
+   *   object should be passed as this parameter.
+   *
+   * @return
+   *   An associative array of all placeholder arguments for this query.
+   */
+  public function getArguments(PlaceholderInterface $queryPlaceholder = NULL);
+
+  /* Query building operations */
+
+  /**
+   * Sets this query to be DISTINCT.
+   *
+   * @param $distinct
+   *   TRUE to flag this query DISTINCT, FALSE to disable it.
+   * @return SelectQueryInterface
+   *   The called object.
+   */
+  public function distinct($distinct = TRUE);
+
+  /**
+   * Adds a field to the list to be SELECTed.
+   *
+   * @param $table_alias
+   *   The name of the table from which the field comes, as an alias. Generally
+   *   you will want to use the return value of join() here to ensure that it is
+   *   valid.
+   * @param $field
+   *   The name of the field.
+   * @param $alias
+   *   The alias for this field. If not specified, one will be generated
+   *   automatically based on the $table_alias and $field. The alias will be
+   *   checked for uniqueness, so the requested alias may not be the alias
+   *   that is assigned in all cases.
+   * @return
+   *   The unique alias that was assigned for this field.
+   */
+  public function addField($table_alias, $field, $alias = NULL);
+
+  /**
+   * Add multiple fields from the same table to be SELECTed.
+   *
+   * This method does not return the aliases set for the passed fields. In the
+   * majority of cases that is not a problem, as the alias will be the field
+   * name. However, if you do need to know the alias you can call getFields()
+   * and examine the result to determine what alias was created. Alternatively,
+   * simply use addField() for the few fields you care about and this method for
+   * the rest.
+   *
+   * @param $table_alias
+   *   The name of the table from which the field comes, as an alias. Generally
+   *   you will want to use the return value of join() here to ensure that it is
+   *   valid.
+   * @param $fields
+   *   An indexed array of fields present in the specified table that should be
+   *   included in this query. If not specified, $table_alias.* will be generated
+   *   without any aliases.
+   * @return Drupal\Core\Database\Query\SelectInterface
+   *   The called object.
+   */
+  public function fields($table_alias, array $fields = 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
+   * various functions, which may in some cases be database-dependent. This
+   * method makes no effort to correct for database-specific functions.
+   *
+   * @param $expression
+   *   The expression string. May contain placeholders.
+   * @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 assigned
+   *   in all cases.
+   * @param $arguments
+   *   Any placeholder arguments needed for this expression.
+   * @return
+   *   The unique alias that was assigned for this expression.
+   */
+  public function addExpression($expression, $alias = NULL, $arguments = array());
+
+  /**
+   * Default Join against another table in the database.
+   *
+   * This method is a convenience method for innerJoin().
+   *
+   * @param $table
+   *   The table against which to join.
+   * @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.
+   * @param $condition
+   *   The condition on which to join this table. If the join requires values,
+   *   this clause should use a named placeholder and the value or values to
+   *   insert should be passed in the 4th parameter. For the first table joined
+   *   on a query, this value is ignored as the first table is taken as the base
+   *   table. The token %alias can be used in this string to be replaced with
+   *   the actual alias. This is useful when $alias is modified by the database
+   *   system, for example, when joining the same table more than once.
+   * @param $arguments
+   *   An array of arguments to replace into the $condition of this join.
+   * @return
+   *   The unique alias that was assigned for this table.
+   */
+  public function join($table, $alias = NULL, $condition = NULL, $arguments = array());
+
+  /**
+   * Inner Join against another table in the database.
+   *
+   * @param $table
+   *   The table against which to join.
+   * @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.
+   * @param $condition
+   *   The condition on which to join this table. If the join requires values,
+   *   this clause should use a named placeholder and the value or values to
+   *   insert should be passed in the 4th parameter. For the first table joined
+   *   on a query, this value is ignored as the first table is taken as the base
+   *   table. The token %alias can be used in this string to be replaced with
+   *   the actual alias. This is useful when $alias is modified by the database
+   *   system, for example, when joining the same table more than once.
+   * @param $arguments
+   *   An array of arguments to replace into the $condition of this join.
+   * @return
+   *   The unique alias that was assigned for this table.
+   */
+  public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = array());
+
+  /**
+   * Left Outer Join against another table in the database.
+   *
+   * @param $table
+   *   The table against which to join.
+   * @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.
+   * @param $condition
+   *   The condition on which to join this table. If the join requires values,
+   *   this clause should use a named placeholder and the value or values to
+   *   insert should be passed in the 4th parameter. For the first table joined
+   *   on a query, this value is ignored as the first table is taken as the base
+   *   table. The token %alias can be used in this string to be replaced with
+   *   the actual alias. This is useful when $alias is modified by the database
+   *   system, for example, when joining the same table more than once.
+   * @param $arguments
+   *   An array of arguments to replace into the $condition of this join.
+   * @return
+   *   The unique alias that was assigned for this table.
+   */
+  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array());
+
+  /**
+   * Right Outer Join against another table in the database.
+   *
+   * @param $table
+   *   The table against which to join.
+   * @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.
+   * @param $condition
+   *   The condition on which to join this table. If the join requires values,
+   *   this clause should use a named placeholder and the value or values to
+   *   insert should be passed in the 4th parameter. For the first table joined
+   *   on a query, this value is ignored as the first table is taken as the base
+   *   table. The token %alias can be used in this string to be replaced with
+   *   the actual alias. This is useful when $alias is modified by the database
+   *   system, for example, when joining the same table more than once.
+   * @param $arguments
+   *   An array of arguments to replace into the $condition of this join.
+   * @return
+   *   The unique alias that was assigned for this table.
+   */
+  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array());
+
+  /**
+   * Join against another table in the database.
+   *
+   * This method does the "hard" work of queuing up a table to be joined against.
+   * 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. 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,
+   *   one will be dynamically generated.
+   * @param $condition
+   *   The condition on which to join this table. If the join requires values,
+   *   this clause should use a named placeholder and the value or values to
+   *   insert should be passed in the 4th parameter. For the first table joined
+   *   on a query, this value is ignored as the first table is taken as the base
+   *   table. The token %alias can be used in this string to be replaced with
+   *   the actual alias. This is useful when $alias is modified by the database
+   *   system, for example, when joining the same table more than once.
+   * @param $arguments
+   *   An array of arguments to replace into the $condition of this join.
+   * @return
+   *   The unique alias that was assigned for this table.
+   */
+  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array());
+
+  /**
+   * Orders the result set by a given field.
+   *
+   * If called multiple times, the query will order by each specified field in the
+   * order this method is called.
+   *
+   * If the query uses DISTINCT or GROUP BY conditions, fields or expressions
+   * that are used for the order must be selected to be compatible with some
+   * databases like PostgreSQL. The PostgreSQL driver can handle simple cases
+   * automatically but it is suggested to explicitly specify them. Additionally,
+   * when ordering on an alias, the alias must be added before orderBy() is
+   * called.
+   *
+   * @param $field
+   *   The field on which to order.
+   * @param $direction
+   *   The direction to sort. Legal values are "ASC" and "DESC".
+   * @return Drupal\Core\Database\Query\SelectInterface
+   *   The called object.
+   */
+  public function orderBy($field, $direction = 'ASC');
+
+  /**
+   * Orders the result set by a random value.
+   *
+   * This may be stacked with other orderBy() calls. If so, the query will order
+   * by each specified field, including this one, in the order called. Although
+   * this method may be called multiple times on the same query, doing so
+   * is not particularly useful.
+   *
+   * Note: The method used by most drivers may not scale to very large result
+   * sets. If you need to work with extremely large data sets, you may create
+   * your own database driver by subclassing off of an existing driver and
+   * implementing your own randomization mechanism. See
+   *
+   * http://jan.kneschke.de/projects/mysql/order-by-rand/
+   *
+   * for an example of such an alternate sorting mechanism.
+   *
+   * @return Drupal\Core\Database\Query\SelectInterface
+   *   The called object
+   */
+  public function orderRandom();
+
+  /**
+   * Restricts a query to a given range in the result set.
+   *
+   * If this method is called with no parameters, will remove any range
+   * directives that have been set.
+   *
+   * @param $start
+   *   The first record from the result set to return. If NULL, removes any
+   *   range directives that are set.
+   * @param $length
+   *   The number of records to return from the result set.
+   * @return Drupal\Core\Database\Query\SelectInterface
+   *   The called object.
+   */
+  public function range($start = NULL, $length = NULL);
+
+  /**
+   * Add another Select query to UNION to this one.
+   *
+   * Union queries consist of two or more queries whose
+   * results are effectively concatenated together. Queries
+   * will be UNIONed in the order they are specified, with
+   * this object's query coming first. Duplicate columns will
+   * be discarded. All forms of UNION are supported, using
+   * the second '$type' argument.
+   *
+   * Note: All queries UNIONed together must have the same
+   * field structure, in the same order. It is up to the
+   * caller to ensure that they match properly. If they do
+   * not, an SQL syntax error will result.
+   *
+   * @param $query
+   *   The query to UNION to this query.
+   * @param $type
+   *   The type of UNION to add to the query. Defaults to plain
+   *   UNION.
+   * @return Drupal\Core\Database\Query\SelectInterface
+   *   The called object.
+   */
+  public function union(SelectInterface $query, $type = '');
+
+  /**
+   * Groups the result set by the specified field.
+   *
+   * @param $field
+   *   The field on which to group. This should be the field as aliased.
+   * @return Drupal\Core\Database\Query\SelectInterface
+   *   The called object.
+   */
+  public function groupBy($field);
+
+  /**
+   * Get the equivalent COUNT query of this query as a new query object.
+   *
+   * @return Drupal\Core\Database\Query\SelectInterface
+   *   A new SelectQuery object with no fields or expressions besides COUNT(*).
+   */
+  public function countQuery();
+
+  /**
+   * Indicates if preExecute() has already been called on that object.
+   *
+   * @return
+   *   TRUE is this query has already been prepared, FALSE otherwise.
+   */
+  public function isPrepared();
+
+  /**
+   * Generic preparation and validation for a SELECT query.
+   *
+   * @return
+   *   TRUE if the validation was successful, FALSE if not.
+   */
+  public function preExecute(SelectInterface $query = NULL);
+
+  /**
+   * Helper function to build most common HAVING conditional clauses.
+   *
+   * This method can take a variable number of parameters. If called with two
+   * parameters, they are taken as $field and $value with $operator having a value
+   * of IN if $value is an array and = otherwise.
+   *
+   * @param $field
+   *   The name of the field to check. If you would like to add a more complex
+   *   condition involving operators or functions, use having().
+   * @param $value
+   *   The value to test the field against. In most cases, this is a scalar. For more
+   *   complex options, it is an array. The meaning of each element in the array is
+   *   dependent on the $operator.
+   * @param $operator
+   *   The comparison operator, such as =, <, or >=. It also accepts more complex
+   *   options such as IN, LIKE, or BETWEEN. Defaults to IN if $value is an array
+   *   = otherwise.
+   * @return Drupal\Core\Database\Query\ConditionInterface
+   *   The called object.
+   */
+  public function havingCondition($field, $value = NULL, $operator = NULL);
+
+  /**
+   * Clone magic method.
+   *
+   * Select queries have dependent objects that must be deep-cloned.  The
+   * connection object itself, however, should not be cloned as that would
+   * duplicate the connection itself.
+   */
+  public function __clone();
+
+  /**
+   * Add FOR UPDATE to the query.
+   *
+   * FOR UPDATE prevents the rows retrieved by the SELECT statement from being
+   * modified or deleted by other transactions until the current transaction
+   * ends. Other transactions that attempt UPDATE, DELETE, or SELECT FOR UPDATE
+   * of these rows will be blocked until the current transaction ends.
+   *
+   * @param $set
+   *   IF TRUE, FOR UPDATE will be added to the query, if FALSE then it won't.
+   *
+   * @return Drupal\Core\Database\Query\ConditionInterface
+   *   The called object.
+   */
+  public function forUpdate($set = TRUE);
+}
diff --git a/core/lib/Drupal/Core/Database/Query/Truncate.php b/core/lib/Drupal/Core/Database/Query/Truncate.php
new file mode 100644
index 0000000000000000000000000000000000000000..263acf50ab60a5ce875c1312b6c575ec24f76df5
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/Truncate.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\Truncate
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection;
+
+
+/**
+ * General class for an abstracted TRUNCATE operation.
+ */
+class Truncate extends Query {
+
+  /**
+   * The table to truncate.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * Constructs a Truncate query object.
+   *
+   * @param DatabaseConnection $connection
+   *   A DatabaseConnection object.
+   * @param string $table
+   *   Name of the table to associate with this query.
+   * @param array $options
+   *   Array of database options.
+   */
+  public function __construct(Connection $connection, $table, array $options = array()) {
+    $options['return'] = Database::RETURN_AFFECTED;
+    parent::__construct($connection, $options);
+    $this->table = $table;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compile().
+   */
+  public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
+    return $this->condition->compile($connection, $queryPlaceholder);
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compiled().
+   */
+  public function compiled() {
+    return $this->condition->compiled();
+  }
+
+  /**
+   * Executes the TRUNCATE query.
+   *
+   * @return
+   *   Return value is dependent on the database type.
+   */
+  public function execute() {
+    return $this->connection->query((string) $this, array(), $this->queryOptions);
+  }
+
+  /**
+   * Implements PHP magic __toString method to convert the query to a string.
+   *
+   * @return string
+   *   The prepared statement.
+   */
+  public function __toString() {
+    // Create a sanitized comment string to prepend to the query.
+    $comments = $this->connection->makeComment($this->comments);
+
+    return $comments . 'TRUNCATE {' . $this->connection->escapeTable($this->table) . '} ';
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/Query/Update.php b/core/lib/Drupal/Core/Database/Query/Update.php
new file mode 100644
index 0000000000000000000000000000000000000000..5ffdb33dba244ff239eb785379dbc7e1b15d3f51
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Query/Update.php
@@ -0,0 +1,268 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Query\Update
+ */
+
+namespace Drupal\Core\Database\Query;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection;
+
+/**
+ * General class for an abstracted UPDATE operation.
+ */
+class Update extends Query implements ConditionInterface {
+
+  /**
+   * The table to update.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * An array of fields that will be updated.
+   *
+   * @var array
+   */
+  protected $fields = array();
+
+  /**
+   * An array of values to update to.
+   *
+   * @var array
+   */
+  protected $arguments = array();
+
+  /**
+   * The condition object for this query.
+   *
+   * Condition handling is handled via composition.
+   *
+   * @var Drupal\Core\Database\Query\Condition
+   */
+  protected $condition;
+
+  /**
+   * Array of fields to update to an expression in case of a duplicate record.
+   *
+   * This variable is a nested array in the following format:
+   * @code
+   * <some field> => array(
+   *  'condition' => <condition to execute, as a string>,
+   *  'arguments' => <array of arguments for condition, or NULL for none>,
+   * );
+   * @endcode
+   *
+   * @var array
+   */
+  protected $expressionFields = array();
+
+  /**
+   * Constructs an Update query object.
+   *
+   * @param Drupal\Core\Database\Connection $connection
+   *   A Connection object.
+   * @param string $table
+   *   Name of the table to associate with this query.
+   * @param array $options
+   *   Array of database options.
+   */
+  public function __construct(Connection $connection, $table, array $options = array()) {
+    $options['return'] = Database::RETURN_AFFECTED;
+    parent::__construct($connection, $options);
+    $this->table = $table;
+
+    $this->condition = new Condition('AND');
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::condition().
+   */
+  public function condition($field, $value = NULL, $operator = NULL) {
+    $this->condition->condition($field, $value, $operator);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::isNull().
+   */
+  public function isNull($field) {
+    $this->condition->isNull($field);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::isNotNull().
+   */
+  public function isNotNull($field) {
+    $this->condition->isNotNull($field);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::exists().
+   */
+  public function exists(SelectInterface $select) {
+    $this->condition->exists($select);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::notExists().
+   */
+  public function notExists(SelectInterface $select) {
+    $this->condition->notExists($select);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::conditions().
+   */
+  public function &conditions() {
+    return $this->condition->conditions();
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::arguments().
+   */
+  public function arguments() {
+    return $this->condition->arguments();
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::where().
+   */
+  public function where($snippet, $args = array()) {
+    $this->condition->where($snippet, $args);
+    return $this;
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compile().
+   */
+  public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
+    return $this->condition->compile($connection, $queryPlaceholder);
+  }
+
+  /**
+   * Implements Drupal\Core\Database\Query\ConditionInterface::compiled().
+   */
+  public function compiled() {
+    return $this->condition->compiled();
+  }
+
+  /**
+   * Adds a set of field->value pairs to be updated.
+   *
+   * @param $fields
+   *   An associative array of fields to write into the database. The array keys
+   *   are the field names and the values are the values to which to set them.
+   *
+   * @return Drupal\Core\Database\Query\Update
+   *   The called object.
+   */
+  public function fields(array $fields) {
+    $this->fields = $fields;
+    return $this;
+  }
+
+  /**
+   * Specifies fields to be updated as an expression.
+   *
+   * Expression fields are cases such as counter=counter+1. This method takes
+   * precedence over fields().
+   *
+   * @param $field
+   *   The field to set.
+   * @param $expression
+   *   The field will be set to the value of this expression. This parameter
+   *   may include named placeholders.
+   * @param $arguments
+   *   If specified, this is an array of key/value pairs for named placeholders
+   *   corresponding to the expression.
+   *
+   * @return Drupal\Core\Database\Query\Update
+   *   The called object.
+   */
+  public function expression($field, $expression, array $arguments = NULL) {
+    $this->expressionFields[$field] = array(
+      'expression' => $expression,
+      'arguments' => $arguments,
+    );
+
+    return $this;
+  }
+
+  /**
+   * Executes the UPDATE query.
+   *
+   * @return
+   *   The number of rows affected by the update.
+   */
+  public function execute() {
+
+    // Expressions take priority over literal fields, so we process those first
+    // and remove any literal fields that conflict.
+    $fields = $this->fields;
+    $update_values = array();
+    foreach ($this->expressionFields as $field => $data) {
+      if (!empty($data['arguments'])) {
+        $update_values += $data['arguments'];
+      }
+      unset($fields[$field]);
+    }
+
+    // Because we filter $fields the same way here and in __toString(), the
+    // placeholders will all match up properly.
+    $max_placeholder = 0;
+    foreach ($fields as $field => $value) {
+      $update_values[':db_update_placeholder_' . ($max_placeholder++)] = $value;
+    }
+
+    if (count($this->condition)) {
+      $this->condition->compile($this->connection, $this);
+      $update_values = array_merge($update_values, $this->condition->arguments());
+    }
+
+    return $this->connection->query((string) $this, $update_values, $this->queryOptions);
+  }
+
+  /**
+   * Implements PHP magic __toString method to convert the query to a string.
+   *
+   * @return string
+   *   The prepared statement.
+   */
+  public function __toString() {
+    // Create a sanitized comment string to prepend to the query.
+    $comments = $this->connection->makeComment($this->comments);
+
+    // Expressions take priority over literal fields, so we process those first
+    // and remove any literal fields that conflict.
+    $fields = $this->fields;
+    $update_fields = array();
+    foreach ($this->expressionFields as $field => $data) {
+      $update_fields[] = $field . '=' . $data['expression'];
+      unset($fields[$field]);
+    }
+
+    $max_placeholder = 0;
+    foreach ($fields as $field => $value) {
+      $update_fields[] = $field . '=:db_update_placeholder_' . ($max_placeholder++);
+    }
+
+    $query = $comments . 'UPDATE {' . $this->connection->escapeTable($this->table) . '} SET ' . implode(', ', $update_fields);
+
+    if (count($this->condition)) {
+      $this->condition->compile($this->connection, $this);
+      // There is an implicit string cast on $this->condition.
+      $query .= "\nWHERE " . $this->condition;
+    }
+
+    return $query;
+  }
+
+}
diff --git a/core/includes/database/schema.inc b/core/lib/Drupal/Core/Database/Schema.php
similarity index 92%
rename from core/includes/database/schema.inc
rename to core/lib/Drupal/Core/Database/Schema.php
index 27934dcdf0410b87a26af9fc0bc397e1c725d3b5..9e2f22e38833bac3f4d6bdd61a1ab151d9294546 100644
--- a/core/includes/database/schema.inc
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -2,10 +2,14 @@
 
 /**
  * @file
- * Generic Database schema code.
+ * Definition of Drupal\Core\Database\Schema
  */
 
-require_once __DIR__ . '/query.inc';
+namespace Drupal\Core\Database;
+
+use Drupal\Core\Database\SchemaObjectExistsException;
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\Query\PlaceholderInterface;
 
 /**
  * @defgroup schemaapi Schema API
@@ -77,7 +81,8 @@
  *       (decimal digits right of the decimal point). Both values are
  *       mandatory. Ignored for other field types.
  *     All parameters apart from 'type' are optional except that type
- *     'numeric' columns must specify 'precision' and 'scale'.
+ *     'numeric' columns must specify 'precision' and 'scale', and type
+ *     'varchar' must specify the 'length' parameter.
  *  - 'primary key': An array of one or more key column specifiers (see below)
  *    that form the primary key.
  *  - 'unique keys': An associative array of unique keys ('keyname' =>
@@ -156,7 +161,7 @@
  * @see drupal_install_schema()
  */
 
-abstract class DatabaseSchema implements QueryPlaceholderInterface {
+abstract class Schema implements PlaceholderInterface {
 
   protected $connection;
 
@@ -194,14 +199,14 @@ public function __clone() {
   }
 
   /**
-   * Implements QueryPlaceHolderInterface::uniqueIdentifier().
+   * Implements PlaceHolderInterface::uniqueIdentifier().
    */
   public function uniqueIdentifier() {
     return $this->uniqueIdentifier;
   }
 
   /**
-   * Implements QueryPlaceHolderInterface::nextPlaceholder().
+   * Implements PlaceHolderInterface::nextPlaceholder().
    */
   public function nextPlaceholder() {
     return $this->placeholder++;
@@ -278,8 +283,8 @@ function prefixNonTable($table) {
    * @param $add_prefix
    *   Boolean to indicate whether the table name needs to be prefixed.
    *
-   * @return QueryConditionInterface
-   *   A DatabaseCondition object.
+   * @return Drupal\Core\Database\Query\ConditionInterface
+   *   A Drupal\Core\Database\Query\Condition object.
    */
   protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) {
     $info = $this->connection->getConnectionOptions();
@@ -287,7 +292,7 @@ protected function buildTableNameCondition($table_name, $operator = '=', $add_pr
     // Retrive the table name and schema
     $table_info = $this->getPrefixInfo($table_name, $add_prefix);
 
-    $condition = new DatabaseCondition('AND');
+    $condition = new Condition('AND');
     $condition->condition('table_catalog', $info['database']);
     $condition->condition('table_schema', $table_info['schema']);
     $condition->condition('table_name', $table_info['table'], $operator);
@@ -379,9 +384,9 @@ abstract public function getFieldTypeMap();
    * @param $new_name
    *   The new name for the table.
    *
-   * @throws DatabaseSchemaObjectDoesNotExistException
+   * @throws Drupal\Core\Database\SchemaObjectDoesNotExistException
    *   If the specified table doesn't exist.
-   * @throws DatabaseSchemaObjectExistsException
+   * @throws Drupal\Core\Database\SchemaObjectExistsException
    *   If a table with the specified new name already exists.
    */
   abstract public function renameTable($table, $new_name);
@@ -419,9 +424,9 @@ abstract public function dropTable($table);
    *   or index including it in this array. See db_change_field() for more
    *   explanation why.
    *
-   * @throws DatabaseSchemaObjectDoesNotExistException
+   * @throws Drupal\Core\Database\SchemaObjectDoesNotExistException
    *   If the specified table doesn't exist.
-   * @throws DatabaseSchemaObjectExistsException
+   * @throws Drupal\Core\Database\SchemaObjectExistsException
    *   If the specified table already has a field by that name.
    */
   abstract public function addField($table, $field, $spec, $keys_new = array());
@@ -450,7 +455,7 @@ abstract public function dropField($table, $field);
    * @param $default
    *   Default value to be set. NULL for 'default NULL'.
    *
-   * @throws DatabaseSchemaObjectDoesNotExistException
+   * @throws Drupal\Core\Database\SchemaObjectDoesNotExistException
    *   If the specified table or field doesn't exist.
    */
   abstract public function fieldSetDefault($table, $field, $default);
@@ -463,7 +468,7 @@ abstract public function fieldSetDefault($table, $field, $default);
    * @param $field
    *   The field to be altered.
    *
-   * @throws DatabaseSchemaObjectDoesNotExistException
+   * @throws Drupal\Core\Database\SchemaObjectDoesNotExistException
    *   If the specified table or field doesn't exist.
    */
   abstract public function fieldSetNoDefault($table, $field);
@@ -489,9 +494,9 @@ abstract public function indexExists($table, $name);
    * @param $fields
    *   Fields for the primary key.
    *
-   * @throws DatabaseSchemaObjectDoesNotExistException
+   * @throws Drupal\Core\Database\SchemaObjectDoesNotExistException
    *   If the specified table doesn't exist.
-   * @throws DatabaseSchemaObjectExistsException
+   * @throws Drupal\Core\Database\SchemaObjectExistsException
    *   If the specified table already has a primary key.
    */
   abstract public function addPrimaryKey($table, $fields);
@@ -518,9 +523,9 @@ abstract public function dropPrimaryKey($table);
    * @param $fields
    *   An array of field names.
    *
-   * @throws DatabaseSchemaObjectDoesNotExistException
+   * @throws Drupal\Core\Database\SchemaObjectDoesNotExistException
    *   If the specified table doesn't exist.
-   * @throws DatabaseSchemaObjectExistsException
+   * @throws Drupal\Core\Database\SchemaObjectExistsException
    *   If the specified table already has a key by that name.
    */
   abstract public function addUniqueKey($table, $name, $fields);
@@ -549,9 +554,9 @@ abstract public function dropUniqueKey($table, $name);
    * @param $fields
    *   An array of field names.
    *
-   * @throws DatabaseSchemaObjectDoesNotExistException
+   * @throws Drupal\Core\Database\SchemaObjectDoesNotExistException
    *   If the specified table doesn't exist.
-   * @throws DatabaseSchemaObjectExistsException
+   * @throws Drupal\Core\Database\SchemaObjectExistsException
    *   If the specified table already has an index by that name.
    */
   abstract public function addIndex($table, $name, $fields);
@@ -645,12 +650,12 @@ abstract public function changeField($table, $field, $field_new, $spec, $keys_ne
    * @param $table
    *   A Schema API table definition array.
    *
-   * @throws DatabaseSchemaObjectExistsException
+   * @throws Drupal\Core\Database\SchemaObjectExistsException
    *   If the specified table already exists.
    */
   public function createTable($name, $table) {
     if ($this->tableExists($name)) {
-      throw new DatabaseSchemaObjectExistsException(t('Table %name already exists.', array('%name' => $name)));
+      throw new SchemaObjectExistsException(t('Table %name already exists.', array('%name' => $name)));
     }
     $statements = $this->createTableSql($name, $table);
     foreach ($statements as $statement) {
@@ -698,26 +703,3 @@ public function prepareComment($comment, $length = NULL) {
     return $this->connection->quote($comment);
   }
 }
-
-/**
- * Exception thrown if an object being created already exists.
- *
- * For example, this exception should be thrown whenever there is an attempt to
- * create a new database table, field, or index that already exists in the
- * database schema.
- */
-class DatabaseSchemaObjectExistsException extends Exception {}
-
-/**
- * Exception thrown if an object being modified doesn't exist yet.
- *
- * For example, this exception should be thrown whenever there is an attempt to
- * modify a database table, field, or index that does not currently exist in
- * the database schema.
- */
-class DatabaseSchemaObjectDoesNotExistException extends Exception {}
-
-/**
- * @} End of "defgroup schemaapi".
- */
-
diff --git a/core/lib/Drupal/Core/Database/SchemaException.php b/core/lib/Drupal/Core/Database/SchemaException.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ae72b491489670a08c7c4f8f4aee961bc36414c
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/SchemaException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\SchemaException
+ */
+
+namespace Drupal\Core\Database;
+
+use RuntimeException;
+
+/**
+ * Base exception for Schema-related errors.
+ */
+class SchemaException extends RuntimeException implements DatabaseException { }
diff --git a/core/lib/Drupal/Core/Database/SchemaObjectDoesNotExistException.php b/core/lib/Drupal/Core/Database/SchemaObjectDoesNotExistException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ac5a1f8828b958164bd34b901e1f7981e680e5fc
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/SchemaObjectDoesNotExistException.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\SchemaObjectDoesNotExistException
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Exception thrown if an object being modified doesn't exist yet.
+ *
+ * For example, this exception should be thrown whenever there is an attempt to
+ * modify a database table, field, or index that does not currently exist in
+ * the database schema.
+ */
+class SchemaObjectDoesNotExistException extends SchemaException implements DatabaseException { }
diff --git a/core/lib/Drupal/Core/Database/SchemaObjectExistsException.php b/core/lib/Drupal/Core/Database/SchemaObjectExistsException.php
new file mode 100644
index 0000000000000000000000000000000000000000..e8221b5267c2f6e41e93e24a328d4746d964d1ea
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/SchemaObjectExistsException.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\SchemaObjectExistsException
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Exception thrown if an object being created already exists.
+ *
+ * For example, this exception should be thrown whenever there is an attempt to
+ * create a new database table, field, or index that already exists in the
+ * database schema.
+ */
+class SchemaObjectExistsException extends SchemaException implements DatabaseException { }
diff --git a/core/lib/Drupal/Core/Database/Statement.php b/core/lib/Drupal/Core/Database/Statement.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b23ed3d6a04e29f8032e6713fe0821ba1a6313d
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Statement.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\StatementBase
+ */
+
+namespace Drupal\Core\Database;
+
+use PDO;
+use PDOStatement;
+
+/**
+ * Default implementation of DatabaseStatementInterface.
+ *
+ * PDO allows us to extend the PDOStatement class to provide additional
+ * functionality beyond that offered by default. We do need extra
+ * functionality. By default, this class is not driver-specific. If a given
+ * driver needs to set a custom statement class, it may do so in its
+ * constructor.
+ *
+ * @see http://us.php.net/pdostatement
+ */
+class Statement extends PDOStatement implements StatementInterface {
+
+  /**
+   * Reference to the database connection object for this statement.
+   *
+   * The name $dbh is inherited from PDOStatement.
+   *
+   * @var DatabaseConnection
+   */
+  public $dbh;
+
+  protected function __construct($dbh) {
+    $this->dbh = $dbh;
+    $this->setFetchMode(PDO::FETCH_OBJ);
+  }
+
+  public function execute($args = array(), $options = array()) {
+    if (isset($options['fetch'])) {
+      if (is_string($options['fetch'])) {
+        // Default to an object. Note: db fields will be added to the object
+        // before the constructor is run. If you need to assign fields after
+        // the constructor is run, see http://drupal.org/node/315092.
+        $this->setFetchMode(PDO::FETCH_CLASS, $options['fetch']);
+      }
+      else {
+        $this->setFetchMode($options['fetch']);
+      }
+    }
+
+    $logger = $this->dbh->getLogger();
+    if (!empty($logger)) {
+      $query_start = microtime(TRUE);
+    }
+
+    $return = parent::execute($args);
+
+    if (!empty($logger)) {
+      $query_end = microtime(TRUE);
+      $logger->log($this, $args, $query_end - $query_start);
+    }
+
+    return $return;
+  }
+
+  public function getQueryString() {
+    return $this->queryString;
+  }
+
+  public function fetchCol($index = 0) {
+    return $this->fetchAll(PDO::FETCH_COLUMN, $index);
+  }
+
+  public function fetchAllAssoc($key, $fetch = NULL) {
+    $return = array();
+    if (isset($fetch)) {
+      if (is_string($fetch)) {
+        $this->setFetchMode(PDO::FETCH_CLASS, $fetch);
+      }
+      else {
+        $this->setFetchMode($fetch);
+      }
+    }
+
+    foreach ($this as $record) {
+      $record_key = is_object($record) ? $record->$key : $record[$key];
+      $return[$record_key] = $record;
+    }
+
+    return $return;
+  }
+
+  public function fetchAllKeyed($key_index = 0, $value_index = 1) {
+    $return = array();
+    $this->setFetchMode(PDO::FETCH_NUM);
+    foreach ($this as $record) {
+      $return[$record[$key_index]] = $record[$value_index];
+    }
+    return $return;
+  }
+
+  public function fetchField($index = 0) {
+    // Call PDOStatement::fetchColumn to fetch the field.
+    return $this->fetchColumn($index);
+  }
+
+  public function fetchAssoc() {
+    // Call PDOStatement::fetch to fetch the row.
+    return $this->fetch(PDO::FETCH_ASSOC);
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/StatementEmpty.php b/core/lib/Drupal/Core/Database/StatementEmpty.php
new file mode 100644
index 0000000000000000000000000000000000000000..84ccb6a2ab5843630af916a9b99d561d07806708
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/StatementEmpty.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\StatementEmpty
+ */
+
+namespace Drupal\Core\Database;
+
+use Iterator;
+
+/**
+ * Empty implementation of a database statement.
+ *
+ * This class satisfies the requirements of being a database statement/result
+ * object, but does not actually contain data.  It is useful when developers
+ * need to safely return an "empty" result set without connecting to an actual
+ * database.  Calling code can then treat it the same as if it were an actual
+ * result set that happens to contain no records.
+ *
+ * @see SearchQuery
+ */
+class StatementEmpty implements Iterator, StatementInterface {
+
+  public function execute($args = array(), $options = array()) {
+    return FALSE;
+  }
+
+  public function getQueryString() {
+    return '';
+  }
+
+  public function rowCount() {
+    return 0;
+  }
+
+  public function setFetchMode($mode, $a1 = NULL, $a2 = array()) {
+    return;
+  }
+
+  public function fetch($mode = NULL, $cursor_orientation = NULL, $cursor_offset = NULL) {
+    return NULL;
+  }
+
+  public function fetchField($index = 0) {
+    return NULL;
+  }
+
+  public function fetchObject() {
+    return NULL;
+  }
+
+  public function fetchAssoc() {
+    return NULL;
+  }
+
+  function fetchAll($mode = NULL, $column_index = NULL, array $constructor_arguments = array()) {
+    return array();
+  }
+
+  public function fetchCol($index = 0) {
+    return array();
+  }
+
+  public function fetchAllKeyed($key_index = 0, $value_index = 1) {
+    return array();
+  }
+
+  public function fetchAllAssoc($key, $fetch = NULL) {
+    return array();
+  }
+
+  /* Implementations of Iterator. */
+
+  public function current() {
+    return NULL;
+  }
+
+  public function key() {
+    return NULL;
+  }
+
+  public function rewind() {
+    // Nothing to do: our DatabaseStatement can't be rewound.
+  }
+
+  public function next() {
+    // Do nothing, since this is an always-empty implementation.
+  }
+
+  public function valid() {
+    return FALSE;
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/StatementInterface.php b/core/lib/Drupal/Core/Database/StatementInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..2fb57fcf14a752b4452c38d021c6737a78a3c024
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/StatementInterface.php
@@ -0,0 +1,199 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\StatementInterface
+ */
+
+namespace Drupal\Core\Database;
+
+use Traversable;
+
+/**
+ * Represents a prepared statement.
+ *
+ * Some methods in that class are purposefully commented out. Due to a change in
+ * how PHP defines PDOStatement, we can't define a signature for those methods
+ * that will work the same way between versions older than 5.2.6 and later
+ * versions.  See http://bugs.php.net/bug.php?id=42452 for more details.
+ *
+ * Child implementations should either extend PDOStatement:
+ * @code
+ * class Drupal\Core\Database\Driver\oracle\Statement extends PDOStatement implements Drupal\Core\Database\StatementInterface {}
+ * @endcode
+ * or define their own class. If defining their own class, they will also have
+ * to implement either the Iterator or IteratorAggregate interface before
+ * Drupal\Core\Database\StatementInterface:
+ * @code
+ * class Drupal\Core\Database\Driver\oracle\Statement implements Iterator, Drupal\Core\Database\StatementInterface {}
+ * @endcode
+ */
+interface StatementInterface extends Traversable {
+
+  /**
+   * Executes a prepared statement
+   *
+   * @param $args
+   *   An array of values with as many elements as there are bound parameters in
+   *   the SQL statement being executed.
+   * @param $options
+   *   An array of options for this query.
+   *
+   * @return
+   *   TRUE on success, or FALSE on failure.
+   */
+  public function execute($args = array(), $options = array());
+
+  /**
+   * Gets the query string of this statement.
+   *
+   * @return
+   *   The query string, in its form with placeholders.
+   */
+  public function getQueryString();
+
+  /**
+   * Returns the number of rows affected by the last SQL statement.
+   *
+   * @return
+   *   The number of rows affected by the last DELETE, INSERT, or UPDATE
+   *   statement executed.
+   */
+  public function rowCount();
+
+  /**
+   * Sets the default fetch mode for this statement.
+   *
+   * See http://php.net/manual/en/pdo.constants.php for the definition of the
+   * constants used.
+   *
+   * @param $mode
+   *   One of the PDO::FETCH_* constants.
+   * @param $a1
+   *   An option depending of the fetch mode specified by $mode:
+   *   - for PDO::FETCH_COLUMN, the index of the column to fetch
+   *   - for PDO::FETCH_CLASS, the name of the class to create
+   *   - for PDO::FETCH_INTO, the object to add the data to
+   * @param $a2
+   *   If $mode is PDO::FETCH_CLASS, the optional arguments to pass to the
+   *   constructor.
+   */
+  // public function setFetchMode($mode, $a1 = NULL, $a2 = array());
+
+  /**
+   * Fetches the next row from a result set.
+   *
+   * See http://php.net/manual/en/pdo.constants.php for the definition of the
+   * constants used.
+   *
+   * @param $mode
+   *   One of the PDO::FETCH_* constants.
+   *   Default to what was specified by setFetchMode().
+   * @param $cursor_orientation
+   *   Not implemented in all database drivers, don't use.
+   * @param $cursor_offset
+   *   Not implemented in all database drivers, don't use.
+   *
+   * @return
+   *   A result, formatted according to $mode.
+   */
+  // public function fetch($mode = NULL, $cursor_orientation = NULL, $cursor_offset = NULL);
+
+  /**
+   * Returns a single field from the next record of a result set.
+   *
+   * @param $index
+   *   The numeric index of the field to return. Defaults to the first field.
+   *
+   * @return
+   *   A single field from the next record, or FALSE if there is no next record.
+   */
+  public function fetchField($index = 0);
+
+  /**
+   * Fetches the next row and returns it as an object.
+   *
+   * The object will be of the class specified by DatabaseStatementInterface::setFetchMode()
+   * or stdClass if not specified.
+   */
+  // public function fetchObject();
+
+  /**
+   * Fetches the next row and returns it as an associative array.
+   *
+   * This method corresponds to PDOStatement::fetchObject(), but for associative
+   * arrays. For some reason PDOStatement does not have a corresponding array
+   * helper method, so one is added.
+   *
+   * @return
+   *   An associative array, or FALSE if there is no next row.
+   */
+  public function fetchAssoc();
+
+  /**
+   * Returns an array containing all of the result set rows.
+   *
+   * @param $mode
+   *   One of the PDO::FETCH_* constants.
+   * @param $column_index
+   *   If $mode is PDO::FETCH_COLUMN, the index of the column to fetch.
+   * @param $constructor_arguments
+   *   If $mode is PDO::FETCH_CLASS, the arguments to pass to the constructor.
+   *
+   * @return
+   *   An array of results.
+   */
+  // function fetchAll($mode = NULL, $column_index = NULL, array $constructor_arguments);
+
+  /**
+   * Returns an entire single column of a result set as an indexed array.
+   *
+   * Note that this method will run the result set to the end.
+   *
+   * @param $index
+   *   The index of the column number to fetch.
+   *
+   * @return
+   *   An indexed array, or an empty array if there is no result set.
+   */
+  public function fetchCol($index = 0);
+
+  /**
+   * Returns the entire result set as a single associative array.
+   *
+   * This method is only useful for two-column result sets. It will return an
+   * associative array where the key is one column from the result set and the
+   * value is another field. In most cases, the default of the first two columns
+   * is appropriate.
+   *
+   * Note that this method will run the result set to the end.
+   *
+   * @param $key_index
+   *   The numeric index of the field to use as the array key.
+   * @param $value_index
+   *   The numeric index of the field to use as the array value.
+   *
+   * @return
+   *   An associative array, or an empty array if there is no result set.
+   */
+  public function fetchAllKeyed($key_index = 0, $value_index = 1);
+
+  /**
+   * Returns the result set as an associative array keyed by the given field.
+   *
+   * If the given key appears multiple times, later records will overwrite
+   * earlier ones.
+   *
+   * @param $key
+   *   The name of the field on which to index the array.
+   * @param $fetch
+   *   The fetchmode to use. If set to PDO::FETCH_ASSOC, PDO::FETCH_NUM, or
+   *   PDO::FETCH_BOTH the returned value with be an array of arrays. For any
+   *   other value it will be an array of objects. By default, the fetch mode
+   *   set for the query will be used.
+   *
+   * @return
+   *   An associative array, or an empty array if there is no result set.
+   */
+  public function fetchAllAssoc($key, $fetch = NULL);
+}
diff --git a/core/includes/database/prefetch.inc b/core/lib/Drupal/Core/Database/StatementPrefetch.php
similarity index 95%
rename from core/includes/database/prefetch.inc
rename to core/lib/Drupal/Core/Database/StatementPrefetch.php
index 4f2b19d1f3d1882c19dbef6264cfb52511ca149a..f860a9ff0909bf9e0d67bdba91a3a2afe13e7068 100644
--- a/core/includes/database/prefetch.inc
+++ b/core/lib/Drupal/Core/Database/StatementPrefetch.php
@@ -2,16 +2,15 @@
 
 /**
  * @file
- * Database interface code for engines that need complete control over their
- * result sets. For example, SQLite will prefix some column names by the name
- * of the table. We post-process the data, by renaming the column names
- * using the same convention as MySQL and PostgreSQL.
+ * Definition of Drupal\Core\Database\StatementPrefetch
  */
 
-/**
- * @ingroup database
- * @{
- */
+namespace Drupal\Core\Database;
+
+use Drupal\Core\Database\Connection;
+use Iterator;
+use PDO;
+use PDOException;
 
 /**
  * An implementation of DatabaseStatementInterface that prefetches all data.
@@ -19,7 +18,7 @@
  * This class behaves very similar to a PDOStatement but as it always fetches
  * every row it is possible to manipulate those results.
  */
-class DatabaseStatementPrefetch implements Iterator, DatabaseStatementInterface {
+class StatementPrefetch implements Iterator, StatementInterface {
 
   /**
    * The query string.
@@ -40,7 +39,7 @@ class DatabaseStatementPrefetch implements Iterator, DatabaseStatementInterface
    *
    * The name $dbh is inherited from PDOStatement.
    *
-   * @var DatabaseConnection
+   * @var Drupal\Core\Database\Connection
    */
   public $dbh;
 
@@ -125,7 +124,7 @@ class DatabaseStatementPrefetch implements Iterator, DatabaseStatementInterface
     'column' => 0,
   );
 
-  public function __construct(DatabaseConnection $connection, $query, array $driver_options = array()) {
+  public function __construct(Connection $connection, $query, array $driver_options = array()) {
     $this->dbh = $connection;
     $this->queryString = $query;
     $this->driverOptions = $driver_options;
@@ -500,8 +499,3 @@ public function fetchAllAssoc($key, $fetch_style = NULL) {
   }
 
 }
-
-/**
- * @} End of "ingroup database".
- */
-
diff --git a/core/lib/Drupal/Core/Database/Transaction.php b/core/lib/Drupal/Core/Database/Transaction.php
new file mode 100644
index 0000000000000000000000000000000000000000..10adadb7111f08cb2a191f2d9f48a4f3f3f5fdac
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/Transaction.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\Transaction
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * A wrapper class for creating and managing database transactions.
+ *
+ * Not all databases or database configurations support transactions. For
+ * example, MySQL MyISAM tables do not. It is also easy to begin a transaction
+ * and then forget to commit it, which can lead to connection errors when
+ * another transaction is started.
+ *
+ * This class acts as a wrapper for transactions. To begin a transaction,
+ * simply instantiate it. When the object goes out of scope and is destroyed
+ * it will automatically commit. It also will check to see if the specified
+ * connection supports transactions. If not, it will simply skip any transaction
+ * commands, allowing user-space code to proceed normally. The only difference
+ * is that rollbacks won't actually do anything.
+ *
+ * In the vast majority of cases, you should not instantiate this class
+ * directly. Instead, call ->startTransaction(), from the appropriate connection
+ * object.
+ */
+class Transaction {
+
+  /**
+   * The connection object for this transaction.
+   *
+   * @var Drupal\Core\Database\Connection
+   */
+  protected $connection;
+
+  /**
+   * A boolean value to indicate whether this transaction has been rolled back.
+   *
+   * @var Boolean
+   */
+  protected $rolledBack = FALSE;
+
+  /**
+   * The name of the transaction.
+   *
+   * This is used to label the transaction savepoint. It will be overridden to
+   * 'drupal_transaction' if there is no transaction depth.
+   */
+  protected $name;
+
+  public function __construct(Connection &$connection, $name = NULL) {
+    $this->connection = &$connection;
+    // If there is no transaction depth, then no transaction has started. Name
+    // the transaction 'drupal_transaction'.
+    if (!$depth = $connection->transactionDepth()) {
+      $this->name = 'drupal_transaction';
+    }
+    // Within transactions, savepoints are used. Each savepoint requires a
+    // name. So if no name is present we need to create one.
+    elseif (!$name) {
+      $this->name = 'savepoint_' . $depth;
+    }
+    else {
+      $this->name = $name;
+    }
+    $this->connection->pushTransaction($this->name);
+  }
+
+  public function __destruct() {
+    // If we rolled back then the transaction would have already been popped.
+    if (!$this->rolledBack) {
+      $this->connection->popTransaction($this->name);
+    }
+  }
+
+  /**
+   * Retrieves the name of the transaction or savepoint.
+   */
+  public function name() {
+    return $this->name;
+  }
+
+  /**
+   * Rolls back the current transaction.
+   *
+   * This is just a wrapper method to rollback whatever transaction stack we are
+   * currently in, which is managed by the connection object itself. Note that
+   * logging (preferable with watchdog_exception()) needs to happen after a
+   * transaction has been rolled back or the log messages will be rolled back
+   * too.
+   *
+   * @see Drupal\Core\Database\Connection::rollback()
+   * @see watchdog_exception()
+   */
+  public function rollback() {
+    $this->rolledBack = TRUE;
+    $this->connection->rollback($this->name);
+  }
+}
diff --git a/core/lib/Drupal/Core/Database/TransactionCommitFailedException.php b/core/lib/Drupal/Core/Database/TransactionCommitFailedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..6a5309ea823746aacf5f11f275bb3e286e06cd40
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/TransactionCommitFailedException.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\TransactionCommitFailedException
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Exception thrown when a commit() function fails.
+ */
+class TransactionCommitFailedException extends TransactionException implements DatabaseException { }
diff --git a/core/lib/Drupal/Core/Database/TransactionException.php b/core/lib/Drupal/Core/Database/TransactionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..25079f5f23c01e771bc42732b1f4f657373f269c
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/TransactionException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\TransactionException
+ */
+
+namespace Drupal\Core\Database;
+
+use RuntimeException;
+
+/**
+ * Exception thrown by an error in a database transaction.
+ */
+class TransactionException extends RuntimeException implements DatabaseException { }
diff --git a/core/lib/Drupal/Core/Database/TransactionExplicitCommitNotAllowedException.php b/core/lib/Drupal/Core/Database/TransactionExplicitCommitNotAllowedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd4bf23438048fe161abb8af018e835c4b4337a7
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/TransactionExplicitCommitNotAllowedException.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\TransactionExplicitCommitNotAllowedException
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Exception to deny attempts to explicitly manage transactions.
+ *
+ * This exception will be thrown when the PDO connection commit() is called.
+ * Code should never call this method directly.
+ */
+class TransactionExplicitCommitNotAllowedException extends TransactionException implements DatabaseException { }
diff --git a/core/lib/Drupal/Core/Database/TransactionNameNonUniqueException.php b/core/lib/Drupal/Core/Database/TransactionNameNonUniqueException.php
new file mode 100644
index 0000000000000000000000000000000000000000..aef40cb81deb522dac38c5b7df82e5ac79859fe6
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/TransactionNameNonUniqueException.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\TransactionNameNonUniqueException
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Exception thrown when a savepoint or transaction name occurs twice.
+ */
+class TransactionNameNonUniqueException extends TransactionException implements DatabaseException { }
diff --git a/core/lib/Drupal/Core/Database/TransactionNoActiveException.php b/core/lib/Drupal/Core/Database/TransactionNoActiveException.php
new file mode 100644
index 0000000000000000000000000000000000000000..44acede1d55fe2d0c3231583cafcde25fc58736b
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/TransactionNoActiveException.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\TransactionNoActiveException
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Exception for when popTransaction() is called with no active transaction.
+ */
+class TransactionNoActiveException extends TransactionException implements DatabaseException { }
diff --git a/core/lib/Drupal/Core/Database/TransactionOutOfOrderException.php b/core/lib/Drupal/Core/Database/TransactionOutOfOrderException.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e2fe7a90d45760951c75726197a7ee3a3a278a0
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/TransactionOutOfOrderException.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\TransactionOutOfOrderException
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Exception thrown when a rollback() resulted in other active transactions being rolled-back.
+ */
+class TransactionOutOfOrderException extends TransactionException implements DatabaseException { }
diff --git a/core/misc/tabledrag.js b/core/misc/tabledrag.js
index 4315057bff441020b5c4e42b8e3810dfc2d700a0..da10a0e7a1dfa1c2633c7cc010baef7b223890c0 100644
--- a/core/misc/tabledrag.js
+++ b/core/misc/tabledrag.js
@@ -201,6 +201,8 @@ Drupal.tableDrag.prototype.hideColumns = function () {
     // The cookie expires in one year.
     expires: 365
   });
+  // Trigger an event to allow other scripts to react to this display change.
+  $('table.tabledrag-processed').trigger('columnschange', 'hide');
 };
 
 /**
@@ -224,6 +226,8 @@ Drupal.tableDrag.prototype.showColumns = function () {
     // The cookie expires in one year.
     expires: 365
   });
+  // Trigger an event to allow other scripts to react to this display change.
+  $('table.tabledrag-processed').trigger('columnschange', 'show');
 };
 
 /**
diff --git a/core/misc/tableheader.js b/core/misc/tableheader.js
index 63de30c8c655517561163eab3d6b97895e474730..543862cddd2a1b7d7973a89c8e290dd7f68f3683 100644
--- a/core/misc/tableheader.js
+++ b/core/misc/tableheader.js
@@ -27,6 +27,14 @@ Drupal.tableHeader = function (table) {
   this.originalTable = $(table);
   this.originalHeader = $(table).children('thead');
   this.originalHeaderCells = this.originalHeader.find('> tr > th');
+  this.displayWeight = null;
+
+  // React to columns change to avoid making checks in the scroll callback.
+  this.originalTable.bind('columnschange', function (e, display) {
+    // This will force header size to be calculated on scroll.
+    self.widthCalculated = (self.displayWeight !== null && self.displayWeight === display);
+    self.displayWeight = display;
+  });
 
   // Clone the table header so it inherits original jQuery properties. Hide
   // the table to avoid a flash of the header clone upon page load.
@@ -95,11 +103,23 @@ Drupal.tableHeader.prototype.eventhandlerRecalculateStickyHeader = function (eve
   // visible or when forced.
   if (this.stickyVisible && (calculateWidth || !this.widthCalculated)) {
     this.widthCalculated = true;
+    var $that = null;
+    var $stickyCell = null;
+    var display = null;
     // Resize header and its cell widths.
-    this.stickyHeaderCells.each(function (index) {
-      var cellWidth = self.originalHeaderCells.eq(index).css('width');
-      $(this).css('width', cellWidth);
-    });
+    // Only apply width to visible table cells. This prevents the header from
+    // displaying incorrectly when the sticky header is no longer visible.
+    for (var i = 0, il = this.originalHeaderCells.length; i < il; i += 1) {
+      $that = $(this.originalHeaderCells[i]);
+      $stickyCell = this.stickyHeaderCells.eq($that.index());
+      display = $that.css('display');
+      if (display !== 'none') {
+        $stickyCell.css({'width': $that.css('width'), 'display': display});
+      }
+      else {
+        $stickyCell.css('display', 'none');
+      }
+    }
     this.stickyTable.css('width', this.originalTable.css('width'));
   }
 };
diff --git a/core/modules/aggregator/aggregator.admin.inc b/core/modules/aggregator/aggregator.admin.inc
index a728920a660cb163683f3557c297f83b5ce96595..e2c946d40d53f7f16ae83b84efe14f58ecd1254b 100644
--- a/core/modules/aggregator/aggregator.admin.inc
+++ b/core/modules/aggregator/aggregator.admin.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Displays the aggregator administration page.
  *
- * Path: admin/config/services/aggregator
- *
  * @see aggregator_menu()
  */
 function aggregator_admin_overview() {
@@ -59,8 +57,6 @@ function aggregator_view() {
 /**
  * Form constructor for adding and editing feed sources.
  *
- * Path: admin/config/services/aggregator/add/feed
- *
  * @param $feed
  *   If editing a feed, the feed to edit as a PHP stdClass value; if adding a
  *   new feed, NULL.
@@ -215,8 +211,6 @@ function aggregator_form_feed_submit($form, &$form_state) {
 /**
  * Page callback: Deletes a feed.
  *
- * Path: admin/config/services/aggregator/remove/%aggregator_feed
- *
  * @param $feed
  *   An associative array describing the feed to be cleared.
  *
@@ -252,8 +246,6 @@ function aggregator_admin_remove_feed_submit($form, &$form_state) {
 /**
  * Form constructor for importing feeds from OPML.
  *
- * Path: admin/config/services/aggregator/add/opml
- *
  * @ingroup forms
  * @see aggregator_menu()
  * @see aggregator_form_opml_validate()
@@ -413,8 +405,6 @@ function _aggregator_parse_opml($opml) {
 /**
  * Page callback: Refreshes a feed, then redirects to the overview page.
  *
- * Path: admin/config/services/aggregator/update/%aggregator_feed
- *
  * @param $feed
  *   An object describing the feed to be refreshed.
  *
@@ -431,8 +421,6 @@ function aggregator_admin_refresh_feed($feed) {
 /**
  * Form constructor for the aggregator system settings.
  *
- * Path: admin/config/services/aggregator/settings
- *
  * @see aggregator_menu()
  * @see aggregator_admin_form_submit()
  * @ingroup forms
@@ -555,8 +543,6 @@ function aggregator_admin_form_submit($form, &$form_state) {
 /**
  * Form constructor to add/edit/delete aggregator categories.
  *
- * Path: admin/config/services/aggregator/add/category
- *
  * @param $edit
  *   An associative array containing:
  *   - title: A string to use for the category title.
diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module
index 81b8c7f334e61bd07d64084185482960f05f02ca..7b65dfa83a1299ae7a359052f27c89b1b7adb4ca 100644
--- a/core/modules/aggregator/aggregator.module
+++ b/core/modules/aggregator/aggregator.module
@@ -268,8 +268,6 @@ function aggregator_menu() {
 /**
  * Title callback: Returns a title for aggregatory category pages.
  *
- * Path: aggregator/categories/%aggregator_category
- *
  * @param $category
  *   An aggregator category.
  *
@@ -283,8 +281,6 @@ function _aggregator_category_title($category) {
 /**
  * Access callback: Determines whether there are any aggregator categories.
  *
- * Path: aggregator/categories
- *
  * @return
  *   TRUE if there is at least one category and the user has access to them;
  *   FALSE otherwise.
diff --git a/core/modules/aggregator/aggregator.pages.inc b/core/modules/aggregator/aggregator.pages.inc
index 353eedca796eced11848e5bb7485332608f790f9..9ca6df5279f85beefe9cd2d4577a9ecdf426ef7d 100644
--- a/core/modules/aggregator/aggregator.pages.inc
+++ b/core/modules/aggregator/aggregator.pages.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Displays the most recent items gathered from any feed.
  *
- * Path: aggregator
- *
  * @see aggregator_menu()
  */
 function aggregator_page_last() {
@@ -23,8 +21,6 @@ function aggregator_page_last() {
 /**
  * Page callback: Displays all the items captured from a particular feed.
  *
- * Path: aggregator/sources/%aggregator_feed
- *
  * @param $feed
  *   The feed for which to display all items.
  *
@@ -44,8 +40,6 @@ function aggregator_page_source($feed) {
 /**
  * Form constructor to show all items captured from a feed.
  *
- * Path: aggregator/sources/%aggregator_feed/categorize
- *
  * @param $feed
  *   The feed for which to list all the aggregated items.
  *
@@ -60,8 +54,6 @@ function aggregator_page_source_form($form, $form_state, $feed) {
 /**
  * Form constructor to list items aggregated in a category.
  *
- * Path: aggregator/categories
- *
  * @param $category
  *   The category for which to list all the aggregated items.
  *
@@ -81,8 +73,6 @@ function aggregator_page_category($category) {
 /**
  * Form constructor to list items aggregated in a category.
  *
- * Path: aggregator/categories/%aggregator_category/categorize
- *
  * @param $category
  *   The category for which to list all the aggregated items.
  *
@@ -342,8 +332,6 @@ function template_preprocess_aggregator_item(&$variables) {
 /**
  * Page callback: Displays all the feeds used by the aggregator.
  *
- * Path: aggregator/sources
- *
  * @see aggregator_menu()
  */
 function aggregator_page_sources() {
@@ -370,8 +358,6 @@ function aggregator_page_sources() {
 /**
  * Page callback: Displays all the categories used by the aggregator.
  *
- * Path: aggregator/categories
- *
  * @see aggregator_menu()
  */
 function aggregator_page_categories() {
@@ -396,8 +382,6 @@ function aggregator_page_categories() {
 /**
  * Page callback: Generates an RSS 0.92 feed of aggregator items or categories.
  *
- * Path: aggregator/rss
- *
  * @see aggregator_menu()
  */
 function aggregator_page_rss() {
@@ -468,8 +452,6 @@ function theme_aggregator_page_rss($variables) {
 /**
  * Page callback: Generates an OPML representation of all feeds.
  *
- * Path: aggregator/opml
- *
  * @param $cid
  *   If set, feeds are exported only from a category with this ID. Otherwise,
  *   all feeds are exported.
diff --git a/core/modules/block/block.admin.css b/core/modules/block/block.admin.css
index 85c2c5fbbfb2cc4c6aa7941f3e34f85193f4f36e..c6b9089166319d8b7edbe211fafd05a9a5902c3a 100644
--- a/core/modules/block/block.admin.css
+++ b/core/modules/block/block.admin.css
@@ -18,7 +18,7 @@
 a.block-demo-backlink,
 a.block-demo-backlink:link,
 a.block-demo-backlink:visited {
-  background-color: #B4D7F0;
+  background-color: #b4d7f0;
   -moz-border-radius: 0 0 10px 10px;
   border-radius: 0 0 10px 10px;
   color: #000;
diff --git a/core/modules/block/block.admin.inc b/core/modules/block/block.admin.inc
index e383e71537605b8c308c0ed6b2fba15862a145cd..8a5553d400537ed4f85b3a56e499f43b53efee80 100644
--- a/core/modules/block/block.admin.inc
+++ b/core/modules/block/block.admin.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Attaches CSS for the block region demo.
  *
- * Path: admin/structure/block/demo/% (for each theme)
- *
  * @see block_menu()
  */
 function block_admin_demo($theme = NULL) {
@@ -20,8 +18,6 @@ function block_admin_demo($theme = NULL) {
 /**
  * Page callback: Shows the block administration page.
  *
- * Path: admin/structure/block
- *
  * @param $theme
  *   The theme to display the administration page for. If not provided, defaults
  *   to the currently used theme.
@@ -257,8 +253,6 @@ function _block_compare($a, $b) {
 /**
  * Form constructor for the block configuration form.
  *
- * Path: admin/structure/block/manage/%/%
- *
  * Also used by block_add_block_form() for adding a new custom block.
  *
  * @param $module
@@ -539,8 +533,6 @@ function block_admin_configure_submit($form, &$form_state) {
 /**
  * Form constructor for the add block form.
  *
- * Path: admin/structure/block/add
- *
  * @see block_menu()
  * @see block_add_block_form_validate()
  * @see block_add_block_form_submit()
@@ -632,8 +624,6 @@ function block_add_block_form_submit($form, &$form_state) {
 /**
  * Form constructor for the custom block deletion form.
  *
- * Path: admin/structure/block/manage/%/%/delete
- *
  * @param $module
  *   The name of the module that implements the block to be deleted. This should
  *   always equal 'block' since it only allows custom blocks to be deleted.
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 4d942edc616e54a195de8dc9404624f895ded5e4..b13a8525f7f69eb6e6c03fddca6bd02c22cff579 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -195,8 +195,6 @@ function _block_themes_access($theme) {
 /**
  * Theme callback: Uses the theme specified in the parameter.
  *
- * Path: admin/structure/block/demo/% (for each theme)
- *
  * @param $theme
  *   The theme whose blocks are being configured. If not set, the default theme
  *   is assumed.
@@ -347,6 +345,16 @@ function block_get_blocks_by_region($region) {
 function _block_get_renderable_region($list = array()) {
   $weight = 0;
   $build = array();
+  // Block caching is not compatible with node_access modules. We also
+  // preserve the submission of forms in blocks, by fetching from cache
+  // only if the request method is 'GET' (or 'HEAD'). User 1 being out of
+  // the regular 'roles define permissions' schema, it brings too many
+  // chances of having unwanted output get in the cache and later be served
+  // to other users. We therefore exclude user 1 from block caching.
+  $not_cacheable = $GLOBALS['user']->uid == 1 ||
+    count(module_implements('node_grants')) ||
+    !in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD'));
+
   foreach ($list as $key => $block) {
     $build[$key] = array(
       '#block' => $block,
@@ -354,18 +362,7 @@ function _block_get_renderable_region($list = array()) {
       '#theme_wrappers' => array('block'),
     );
 
-    // Block caching is not compatible with node_access modules. We also
-    // preserve the submission of forms in blocks, by fetching from cache
-    // only if the request method is 'GET' (or 'HEAD'). User 1 being out of
-    // the regular 'roles define permissions' schema, it brings too many
-    // chances of having unwanted output get in the cache and later be served
-    // to other users. We therefore exclude user 1 from block caching.
-    if (
-      $GLOBALS['user']->uid == 1 ||
-      count(module_implements('node_grants')) ||
-      !in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD')) ||
-      in_array($block->cache, array(DRUPAL_NO_CACHE, DRUPAL_CACHE_CUSTOM))
-    ) {
+    if ($not_cacheable || in_array($block->cache, array(DRUPAL_NO_CACHE, DRUPAL_CACHE_CUSTOM))) {
       // Non-cached blocks get built immediately. Provides more content
       // that can be easily manipulated during hook_page_alter().
       $build[$key] = _block_get_renderable_block($build[$key]);
diff --git a/core/modules/book/book.admin.inc b/core/modules/book/book.admin.inc
index e37c7fc6d05a454d4ad237b6f1d16731750b5435..132f2c619094c8b8c152ec42787d22ab41631c7e 100644
--- a/core/modules/book/book.admin.inc
+++ b/core/modules/book/book.admin.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Returns an administrative overview of all books.
  *
- * Path: admin/content/book
- *
  * @see book_menu()
  */
 function book_admin_overview() {
@@ -28,8 +26,6 @@ function book_admin_overview() {
 /**
  * Form constructor for the book settings form.
  *
- * Path: admin/content/book/settings
- *
  * @see book_menu()
  * @see book_admin_settings_validate()
  * @ingroup forms
@@ -70,8 +66,6 @@ function book_admin_settings_validate($form, &$form_state) {
 /**
  * Form constructor for administering a single book's hierarchy.
  *
- * Path: admin/content/book/%node
- *
  * @param $node
  *   The node of the top-level page in the book.
  *
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index c4fa615202c15605d0cf97ba6d9da2b82b98dd34..282fb46c02ea256e36f80bd7d33209afd4a520ce 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -213,8 +213,6 @@ function _book_outline_access($node) {
 /**
  * Access callback: Determines if the user can remove nodes from the outline.
  *
- * Path: node/%node/outline/remove
- *
  * @param $node
  *   The node to remove from the outline.
  *
diff --git a/core/modules/book/book.pages.inc b/core/modules/book/book.pages.inc
index 98282be6d055d734e0f1cf8bfe07823560d33bbe..4fab6dc42e63898a585a265593a063e9e82bb2fd 100644
--- a/core/modules/book/book.pages.inc
+++ b/core/modules/book/book.pages.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Prints a listing of all books.
  *
- * Path: book
- *
  * @see book_menu()
  */
 function book_render() {
@@ -24,8 +22,6 @@ function book_render() {
 /**
  * Page callback: Generates representations of a book page and its children.
  *
- * Path: book/export/%/%
- *
  * The function delegates the generation of output to helper functions. The
  * function name is derived by prepending 'book_export_' to the given output
  * type. So, e.g., a type of 'html' results in a call to the function
@@ -97,8 +93,6 @@ function book_export_html($nid) {
 /**
  * Page callback: Shows the outline form for a single node.
  *
- * Path: node/%node/outline
- *
  * @param $node
  *   The book node for which to show the outline.
  *
@@ -203,8 +197,6 @@ function book_outline_form_submit($form, &$form_state) {
 /**
  * Form constructor to confirm removal of a node from a book.
  *
- * Path: node/%node/outline/remove
- *
  * @param $node
  *   The node to delete.
  *
diff --git a/core/modules/comment/comment.admin.inc b/core/modules/comment/comment.admin.inc
index 550de56852dc7b792c6d5017859ada9da7dc9040..d00e5f944ddbc4c86f95dfacf4337494d3a5db6d 100644
--- a/core/modules/comment/comment.admin.inc
+++ b/core/modules/comment/comment.admin.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Presents an administrative comment listing.
  *
- * Path: admin/content/comment
- *
  * @param $type
  *   The type of the overview form ('approval' or 'new'). See
  *   comment_admin_overview() for details.
@@ -250,8 +248,6 @@ function comment_multiple_delete_confirm_submit($form, &$form_state) {
 /**
  * Page callback: Shows a confirmation page for comment deletions.
  *
- * Path: comment/%/delete
- *
  * @param $cid
  *   The ID of the comment that is about to be deleted.
  *
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 9ad7cfcfece4c6a6c80be7e00a779d8c03501c9f..3954119f2bb7ebc8323f9ffc643dd437bf975906 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1643,8 +1643,6 @@ function comment_get_display_page($cid, $node_type) {
 /**
  * Page callback: Displays the comment editing form.
  *
- * Path: comment/%comment/edit
- *
  * @param $comment
  *   The comment object representing the comment to be edited.
  *
diff --git a/core/modules/comment/comment.pages.inc b/core/modules/comment/comment.pages.inc
index 5e3d9de40bd11fdb691b36f1fbb75cd244b31dc9..344e75717b72ecee6fc2deb90b70b0b1ee2c1846 100644
--- a/core/modules/comment/comment.pages.inc
+++ b/core/modules/comment/comment.pages.inc
@@ -102,8 +102,6 @@ function comment_reply($node, $pid = NULL) {
 /**
  * Page callback: Publishes the specified comment.
  *
- * Path: comment/%/approve
- *
  * @param $cid
  *   A comment identifier.
  *
diff --git a/core/modules/contact/contact.admin.inc b/core/modules/contact/contact.admin.inc
index 4a8ee39556d72cf8c62cab0326b5c07a8699e891..7b1c90b1a525b35023eb860554b74fd50306b100 100644
--- a/core/modules/contact/contact.admin.inc
+++ b/core/modules/contact/contact.admin.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Lists contact categories.
  *
- * Path: admin/structure/contact
- *
  * @see contact_menu()
  */
 function contact_category_list() {
@@ -59,10 +57,6 @@ function contact_category_list() {
 /**
  * Form constructor for the category edit form.
  *
- * Paths:
- * - admin/structure/contact/add
- * - admin/structure/contact/edit/%contact
- *
  * @param $category
  *   An array describing the category to be edited. May be empty for new
  *   categories. Recognized array keys are:
@@ -197,8 +191,6 @@ function contact_category_edit_form_submit($form, &$form_state) {
 /**
  * Form constructor for the contact category deletion form.
  *
- * Path: admin/structure/contact/delete/%contact
- *
  * @param $contact
  *   Array describing the contact category to be deleted. See the documentation
  *   of contact_category_edit_form() for the recognized keys.
diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module
index 2858e494a4787e2ce9bdb83c906bb3b48441ed32..abc1c6c9a84d67eb1307e6c2d19e408fd505d34b 100644
--- a/core/modules/contact/contact.module
+++ b/core/modules/contact/contact.module
@@ -109,8 +109,6 @@ function contact_menu() {
 /**
  * Access callback: Checks access for a user's personal contact form.
  *
- * Path: user/%user/contact
- *
  * @param $account
  *   The user object of the user whose contact form is being requested.
  *
diff --git a/core/modules/contact/contact.pages.inc b/core/modules/contact/contact.pages.inc
index f17acdf32ad3ff4f919655726aa89139538221ab..289e38b7a2a8b233a3d21c89e245ed49e535bf3e 100644
--- a/core/modules/contact/contact.pages.inc
+++ b/core/modules/contact/contact.pages.inc
@@ -8,8 +8,6 @@
 /**
  * Form constructor for the site-wide contact form.
  *
- * Path: contact
- *
  * @see contact_menu()
  * @see contact_site_form_validate()
  * @see contact_site_form_submit()
@@ -176,8 +174,6 @@ function contact_site_form_submit($form, &$form_state) {
 /**
  * Form constructor for the personal contact form.
  *
- * Path: user/%user/contact
- *
  * @see contact_menu()
  * @see contact_personal_form_validate()
  * @see contact_personal_form_submit()
diff --git a/core/modules/contextual/contextual.info b/core/modules/contextual/contextual.info
index 041f2e3fffccf6df5a02c6b0188befb8768527aa..c9434619be30384e95698cb1419b6d7f64bfc099 100644
--- a/core/modules/contextual/contextual.info
+++ b/core/modules/contextual/contextual.info
@@ -1,4 +1,4 @@
-name = Contextual links
+name = Contextual Links
 description = Provides contextual links to perform actions related to elements on a page.
 package = Core
 version = VERSION
diff --git a/core/modules/contextual/contextual.module b/core/modules/contextual/contextual.module
index 7b14a3fb179d2aa0d4501adf5a2e2fa689434518..fc93466c537a4ce5df9b7d0a03bafda1e855116a 100644
--- a/core/modules/contextual/contextual.module
+++ b/core/modules/contextual/contextual.module
@@ -13,11 +13,11 @@ function contextual_help($path, $arg) {
     case 'admin/help#contextual':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('The Contextual links module displays links related to regions of pages on your site to users with <em>access contextual links</em> permission. For more information, see the online handbook entry for <a href="@contextual">Contextual links module</a>.', array('@contextual' => 'http://drupal.org/handbook/modules/contextual')) . '</p>';
+      $output .= '<p>' . t('The Contextual Links module displays links related to regions of pages on your site to users with <em>access contextual links</em> permission. For more information, see the online handbook entry for <a href="@contextual">Contextual Links module</a>.', array('@contextual' => 'http://drupal.org/handbook/modules/contextual')) . '</p>';
       $output .= '<h3>' . t('Uses') . '</h3>';
       $output .= '<dl>';
       $output .= '<dt>' . t('Displaying contextual links') . '</dt>';
-      $output .= '<dd>' . t('Contextual links are supplied by modules, to give you quick access to tasks associated with regions of pages on your site. For instance, if you have a custom menu block displayed in a sidebar of your site, the Blocks and Menus modules will supply links to configure the block and edit the menu. The Contextual links module collects these links into a list for display by your theme, and also adds JavaScript code to the page to hide the links initially, and display them when your mouse hovers over the block.') . '</dd>';
+      $output .= '<dd>' . t('Contextual links are supplied by modules, to give you quick access to tasks associated with regions of pages on your site. For instance, if you have a custom menu block displayed in a sidebar of your site, the Blocks and Menus modules will supply links to configure the block and edit the menu. The Contextual Links module collects these links into a list for display by your theme, and also adds JavaScript code to the page to hide the links initially, and display them when your mouse hovers over the block.') . '</dd>';
       $output .= '</dl>';
       return $output;
   }
@@ -41,7 +41,7 @@ function contextual_permission() {
 function contextual_library_info() {
   $path = drupal_get_path('module', 'contextual');
   $libraries['contextual-links'] = array(
-    'title' => 'Contextual links',
+    'title' => 'Contextual Links',
     'website' => 'http://drupal.org/node/473268',
     'version' => '1.0',
     'js' => array(
diff --git a/core/modules/dashboard/dashboard.css b/core/modules/dashboard/dashboard.css
index 0570f7e5a985f636d50bfe6f9dd982d3dc3c8729..f68b372da9ff78b039c0983a4edf6185d9c155ab 100644
--- a/core/modules/dashboard/dashboard.css
+++ b/core/modules/dashboard/dashboard.css
@@ -32,7 +32,7 @@
 }
 #dashboard #disabled-blocks .block,
 #dashboard .block-placeholder {
-  background: #E2E1DC;
+  background: #e2e1dc;
   -moz-border-radius: 4px;
   border-radius: 4px;
   float: left; /* LTR */
@@ -43,14 +43,14 @@
   margin: 10px 0 0 0;
 }
 #dashboard .ui-sortable {
-  border: 2px dashed #CCC;
+  border: 2px dashed #ccc;
   padding: 10px;
 }
 #dashboard .canvas-content {
   padding: 10px;
 }
 #dashboard .canvas-content a.button {
-  color: #5A5A5A;
+  color: #5a5a5a;
   margin: 0 0 0 10px; /* LTR */
   text-decoration: none;
 }
@@ -66,8 +66,8 @@
   padding: 0;
 }
 #dashboard #disabled-blocks .region {
-  background-color: #E0E0D8;
-  border: #CCC 1px solid;
+  background-color: #e0e0d8;
+  border: #ccc 1px solid;
   padding: 10px;
 }
 #dashboard #disabled-blocks h2 {
@@ -77,10 +77,10 @@
 }
 #dashboard #disabled-blocks .block {
   background: #444;
-  color: #FFF;
+  color: #fff;
 }
 #dashboard.customize-inactive #disabled-blocks .block:hover {
-  background: #0074BD;
+  background: #0074bd;
 }
 #dashboard #disabled-blocks .block-placeholder {
   height: 1.6em;
@@ -99,10 +99,10 @@
   padding: 0 17px;
 }
 #dashboard.customize-inactive #disabled-blocks .block:hover h2 {
-  background: #0074BD url(../../misc/draggable.png) no-repeat 0px -39px;
-  color: #FFF;
+  background: #0074bd url(../../misc/draggable.png) no-repeat 0px -39px;
+  color: #fff;
 }
 #dashboard.customize-inactive .dashboard-region .ui-sortable .block:hover h2 {
-  background: #0074BD url(../../misc/draggable.png) no-repeat 3px -36px;
-  color: #FFF;
+  background: #0074bd url(../../misc/draggable.png) no-repeat 3px -36px;
+  color: #fff;
 }
diff --git a/core/modules/dblog/dblog.info b/core/modules/dblog/dblog.info
index 2aa61fc0e59c0ad0b970ba1133e9888dec18ff87..50e76d53e63e6e398c5d15616064a4d3dac4b0f6 100644
--- a/core/modules/dblog/dblog.info
+++ b/core/modules/dblog/dblog.info
@@ -1,4 +1,4 @@
-name = Database logging
+name = Database Logging
 description = Logs and records system events to the database.
 package = Core
 version = VERSION
diff --git a/core/modules/dblog/dblog.module b/core/modules/dblog/dblog.module
index 496a043a76a61b0211da64a5a6e630c8a4327b71..9c54ddfd32918695162ec8584d99e780cae7edeb 100644
--- a/core/modules/dblog/dblog.module
+++ b/core/modules/dblog/dblog.module
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * @file
  * System monitoring and logging for administrators.
@@ -19,17 +21,17 @@ function dblog_help($path, $arg) {
     case 'admin/help#dblog':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('The Database logging module logs system events in the Drupal database. For more information, see the online handbook entry for the <a href="@dblog">Database logging module</a>.', array('@dblog' => 'http://drupal.org/handbook/modules/dblog')) . '</p>';
+      $output .= '<p>' . t('The Database Logging module logs system events in the Drupal database. For more information, see the online handbook entry for the <a href="@dblog">Database Logging module</a>.', array('@dblog' => 'http://drupal.org/handbook/modules/dblog')) . '</p>';
       $output .= '<h3>' . t('Uses') . '</h3>';
       $output .= '<dl>';
       $output .= '<dt>' . t('Monitoring your site') . '</dt>';
-      $output .= '<dd>' . t('The Database logging module allows you to view an event log on the <a href="@dblog">Recent log messages</a> page. The log is a chronological list of recorded events containing usage data, performance data, errors, warnings and operational information. Administrators should check the log on a regular basis to ensure their site is working properly.', array('@dblog' => url('admin/reports/dblog'))) . '</dd>';
+      $output .= '<dd>' . t('The Database Logging module allows you to view an event log on the <a href="@dblog">Recent log messages</a> page. The log is a chronological list of recorded events containing usage data, performance data, errors, warnings and operational information. Administrators should check the log on a regular basis to ensure their site is working properly.', array('@dblog' => url('admin/reports/dblog'))) . '</dd>';
       $output .= '<dt>' . t('Debugging site problems') . '</dt>';
       $output .= '<dd>' . t('In case of errors or problems with the site, the <a href="@dblog">Recent log messages</a> page can be useful for debugging, since it shows the sequence of events. The log messages include usage information, warnings, and errors.', array('@dblog' => url('admin/reports/dblog'))) . '</dd>';
       $output .= '</dl>';
       return $output;
     case 'admin/reports/dblog':
-      return '<p>' . t('The Database logging module monitors your website, capturing system events in a log (shown here) to be reviewed by an authorized individual at a later time. This log is a list of recorded events containing usage data, performance data, errors, warnings and operational information. It is vital to check the Recent log messages report on a regular basis, as it is often the only way to tell what is going on.') . '</p>';
+      return '<p>' . t('The Database Logging module monitors your website, capturing system events in a log (shown here) to be reviewed by an authorized individual at a later time. This log is a list of recorded events containing usage data, performance data, errors, warnings and operational information. It is vital to check the Recent log messages report on a regular basis, as it is often the only way to tell what is going on.') . '</p>';
   }
 }
 
diff --git a/core/modules/dblog/dblog.test b/core/modules/dblog/dblog.test
index ffd3e8a56533dd69762549cc2c8d6b6dc316a423..76b5d26098faba4ea5534a50355e9b5d456d3ec7 100644
--- a/core/modules/dblog/dblog.test
+++ b/core/modules/dblog/dblog.test
@@ -129,7 +129,7 @@ class DBLogTestCase extends DrupalWebTestCase {
     $this->drupalGet('admin/help/dblog');
     $this->assertResponse($response);
     if ($response == 200) {
-      $this->assertText(t('Database logging'), t('DBLog help was displayed'));
+      $this->assertText(t('Database Logging'), t('DBLog help was displayed'));
     }
 
     // View dblog report node.
diff --git a/core/modules/entity/entity.query.inc b/core/modules/entity/entity.query.inc
index fde912376993cadd679afa0d00509e27ec8f1345..fb7ebf06ca38cb7532207100983781297ce649f6 100644
--- a/core/modules/entity/entity.query.inc
+++ b/core/modules/entity/entity.query.inc
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Query\Select;
+
 /**
  * @file
  * Entity query API.
@@ -940,7 +942,7 @@ function finishQuery($select_query, $id_key = 'entity_id') {
    *   HAVING or WHERE. This is necessary because SQL can't handle WHERE
    *   conditions on aliased columns.
    */
-  public function addCondition(SelectQuery $select_query, $sql_field, $condition, $having = FALSE) {
+  public function addCondition(Select $select_query, $sql_field, $condition, $having = FALSE) {
     $method = $having ? 'havingCondition' : 'condition';
     $like_prefix = '';
     switch ($condition['operator']) {
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index d1e4f73582a2febc2a069831e2a2c96b77ba7592..64e3e07dcd92b710042c7dad29a7ec0ee698f818 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -340,7 +340,7 @@ function field_help($path, $arg) {
       }
       $output .= theme('item_list', $items) . '</dd>';
       $output .= '<dt>' . t('Managing field data storage') . '</dt>';
-      $output .= '<dd>' . t('Developers of field modules can either use the default <a href="@sql-store">Field SQL storage module</a> to store data for their fields, or a contributed or custom module developed using the <a href="@storage-api">field storage API</a>.', array('@storage-api' => 'http://api.drupal.org/api/group/field_storage/7', '@sql-store' => url('admin/help/field_sql_storage'))) . '</dd>';
+      $output .= '<dd>' . t('Developers of field modules can either use the default <a href="@sql-store">Field SQL Storage module</a> to store data for their fields, or a contributed or custom module developed using the <a href="@storage-api">field storage API</a>.', array('@storage-api' => 'http://api.drupal.org/api/group/field_storage/7', '@sql-store' => url('admin/help/field_sql_storage'))) . '</dd>';
       $output .= '</dl>';
       return $output;
   }
diff --git a/core/modules/field/modules/field_sql_storage/field_sql_storage.info b/core/modules/field/modules/field_sql_storage/field_sql_storage.info
index ee1ae571267b5f584ff98eaf2638a8c50f381971..27816184cf69c496c73ae317ff43b4a025da5898 100644
--- a/core/modules/field/modules/field_sql_storage/field_sql_storage.info
+++ b/core/modules/field/modules/field_sql_storage/field_sql_storage.info
@@ -1,4 +1,4 @@
-name = Field SQL storage
+name = Field SQL Storage
 description = Stores field data in an SQL database.
 package = Core
 version = VERSION
diff --git a/core/modules/field/modules/field_sql_storage/field_sql_storage.module b/core/modules/field/modules/field_sql_storage/field_sql_storage.module
index 92d244a9fbaccdbaba945f2d83843fc471357e29..adc50bd61114661d7259808029aa6a2128a1fb08 100644
--- a/core/modules/field/modules/field_sql_storage/field_sql_storage.module
+++ b/core/modules/field/modules/field_sql_storage/field_sql_storage.module
@@ -1,5 +1,8 @@
 <?php
 
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Query\Select;
+
 /**
  * @file
  * Default implementation of the field storage API.
@@ -13,7 +16,7 @@ function field_sql_storage_help($path, $arg) {
     case 'admin/help#field_sql_storage':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('The Field SQL storage module stores field data in the database. It is the default field storage module; other field storage mechanisms may be available as contributed modules. See the <a href="@field-help">Field module help page</a> for more information about fields.', array('@field-help' => url('admin/help/field'))) . '</p>';
+      $output .= '<p>' . t('The Field SQL Storage module stores field data in the database. It is the default field storage module; other field storage mechanisms may be available as contributed modules. See the <a href="@field-help">Field module help page</a> for more information about fields.', array('@field-help' => url('admin/help/field'))) . '</p>';
       return $output;
   }
 }
@@ -592,7 +595,7 @@ function field_sql_storage_field_storage_query(EntityFieldQuery $query) {
  * @return
  *   The name of the entity base table joined in.
  */
-function _field_sql_storage_query_join_entity(SelectQuery $select_query, $entity_type, $field_base_table) {
+function _field_sql_storage_query_join_entity(Select $select_query, $entity_type, $field_base_table) {
   $entity_info = entity_get_info($entity_type);
   $entity_base_table = $entity_info['base table'];
   $entity_field = $entity_info['entity keys']['id'];
@@ -615,7 +618,7 @@ function _field_sql_storage_query_join_entity(SelectQuery $select_query, $entity
  *   A callback that should return the column name to be used for the field
  *   conditions. Accepts a field name and a field column name as parameters.
  */
-function _field_sql_storage_query_field_conditions(EntityFieldQuery $query, SelectQuery $select_query, $conditions, $table_aliases, $column_callback) {
+function _field_sql_storage_query_field_conditions(EntityFieldQuery $query, Select $select_query, $conditions, $table_aliases, $column_callback) {
   $groups = &drupal_static(__FUNCTION__, array());
   foreach ($conditions as $key => $condition) {
     $table_alias = $table_aliases[$key];
diff --git a/core/modules/field/modules/field_sql_storage/field_sql_storage.test b/core/modules/field/modules/field_sql_storage/field_sql_storage.test
index 773de3d072dc03c2d76b5a94ac2be11301832196..d6c766e9f9462934fe3ab1f830bce59afddc51c5 100644
--- a/core/modules/field/modules/field_sql_storage/field_sql_storage.test
+++ b/core/modules/field/modules/field_sql_storage/field_sql_storage.test
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * @file
  * Tests for field_sql_storage.module.
@@ -14,8 +16,8 @@
 class FieldSqlStorageTestCase extends DrupalWebTestCase {
   public static function getInfo() {
     return array(
-      'name'  => 'Field SQL storage tests',
-      'description'  => "Test field SQL storage module.",
+      'name'  => 'Field SQL Storage tests',
+      'description'  => "Test Field SQL Storage module.",
       'group' => 'Field API'
     );
   }
diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc
index 5457120dfa0a72bdfcfdedf323044607137c9002..cec0d842ca958324c31f0691cc487310d543b54a 100644
--- a/core/modules/field_ui/field_ui.admin.inc
+++ b/core/modules/field_ui/field_ui.admin.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Lists all defined fields for quick reference.
  *
- * Path: admin/reports/fields
- *
  * @see field_ui_menu()
  */
 function field_ui_fields_list() {
@@ -287,9 +285,6 @@ function theme_field_ui_table($variables) {
 /**
  * Form constructor for the 'Manage fields' form of a bundle.
  *
- * Path: BUNDLE_ADMIN_PATH/fields, where BUNDLE_ADMIN_PATH is the path stored in
- * the ['admin']['info'] property in the return value of hook_entity_info().
- *
  * The resulting form allows fields and pseudo-fields to be re-ordered.
  *
  * @see field_ui_menu()
@@ -880,12 +875,6 @@ function field_ui_field_overview_form_submit($form, &$form_state) {
 /**
  * Form constructor for the field display settings for a given view mode.
  *
- * Paths:
- * - BUNDLE_ADMIN_PATH/display
- * - BUNLDE_ADMIN_PATH/display/%view_mode
- * where BUNDLE_ADMIN_PATH is the path stored in the ['admin']['info'] property
- * in the return value of hook_entity_info().
- *
  * @see field_ui_menu()
  * @see field_ui_display_overview_multistep_submit()
  * @see field_ui_display_overview_form_submit()
@@ -1568,10 +1557,6 @@ function field_ui_existing_field_options($entity_type, $bundle) {
 /**
  * Form constructor for the field settings edit page.
  *
- * Path: BUNDLE_ADMIN_PATH/fields/%field/field-settings, where BUNDLE_ADMIN_PATH
- * is the path stored in the ['admin']['info'] property
- * in the return value of hook_entity_info().
- *
  * @see field_ui_menu()
  * @see field_ui_settings_form_submit()
  * @ingroups forms
@@ -1657,10 +1642,6 @@ function field_ui_field_settings_form_submit($form, &$form_state) {
 /**
  * Form constructor for the widget selection form.
  *
- * Path: BUNDLE_ADMIN_PATH/fields/%field/widget-type, where BUNDLE_ADMIN_PATH is
- * the path stored in the ['admin']['info'] property in the return value of
- * hook_entity_info().
- *
  * @see field_ui_menu()
  * @see field_ui_widget_type_form_submit()
  * @ingroup forms
@@ -1739,10 +1720,6 @@ function field_ui_widget_type_form_submit($form, &$form_state) {
 /**
  * Form constructor for removing a field instance from a bundle.
  *
- * Path: BUNDLE_ADMIN_PATH/fields/%field/delete, where BUNDLE_ADMIN_PATH is the
- * path stored in the ['admin']['info'] property in the return value of
- * hook_entity_info().
- *
  * @see field_ui_menu()
  * @see field_ui_field_delete_form_submit()
  * @ingroup forms
@@ -1814,12 +1791,6 @@ function field_ui_field_delete_form_submit($form, &$form_state) {
 /**
  * Form constructor for the field instance settings form.
  *
- * Paths:
- * - BUNDLE_ADMIN_PATH/fields/%field
- * - BUNDLE_ADMIN_PATH/fields/%field/edit
- * where BUNDLE_ADMIN_PATH is the path stored in the ['admin']['info'] property
- * in the return value of hook_entity_info().
- *
  * @see field_ui_menu()
  * @see field_ui_field_edit_form_validate()
  * @see field_ui_field_edit_form_submit()
diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module
index ab807dc36b4ae29ac7c7637468d3a74996844e7d..5ca938f5daa39d9e24cd8b2fb958d0c0de93b1f8 100644
--- a/core/modules/field_ui/field_ui.module
+++ b/core/modules/field_ui/field_ui.module
@@ -239,10 +239,6 @@ function field_ui_menu_load($field_name, $entity_type, $bundle_name, $bundle_pos
 /**
  * Title callback: Returns the name of a given instance.
  *
- * Path: BUNDLE_ADMIN_PATH/fields/%field, where BUNDLE_ADMIN_PATH is the path
- * stored in the ['admin']['info'] property in the return value of
- * hook_entity_info().
- *
  * @see field_ui_menu()
  */
 function field_ui_menu_title($instance) {
@@ -252,9 +248,6 @@ function field_ui_menu_title($instance) {
 /**
  * Access callback: Checks access for the 'view mode display settings' pages.
  *
- * Path: BUNDLE_ADMIN_PATH/display, where BUNDLE_ADMIN_PATH is the path stored
- * in the ['admin']['info'] property in the return value of hook_entity_info().
- *
  * @see field_ui_menu()
  */
 function _field_ui_view_mode_menu_access($entity_type, $bundle, $view_mode, $access_callback) {
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index c9518074221ed34f1820224087ba9c129ac1d031..2141cae59f13108e5797f5a4836f7e9ce4daa72f 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -72,6 +72,7 @@ function file_element_info() {
     '#progress_message' => NULL,
     '#upload_validators' => array(),
     '#upload_location' => NULL,
+    '#size' => 22,
     '#extended' => FALSE,
     '#attached' => array(
       'css' => array($file_path . '/file.admin.css'),
@@ -225,8 +226,6 @@ function file_file_download($uri, $field_type = 'file') {
 /**
  * Ajax callback: Processes file uploads and deletions.
  *
- * Path: file/ajax
- *
  * This rebuilds the form element for a particular field item. As long as the
  * form processing is properly encapsulated in the widget element the form
  * should rebuild correctly using FAPI without the need for additional callbacks
@@ -292,8 +291,6 @@ function file_ajax_upload() {
 /**
  * Ajax callback: Retrieves upload progress.
  *
- * Path: file/progress
- *
  * @param $key
  *   The unique key for this upload process.
  */
@@ -447,7 +444,7 @@ function file_managed_file_process($element, &$form_state, $form) {
     '#type' => 'file',
     '#title' => t('Choose a file'),
     '#title_display' => 'invisible',
-    '#size' => 22,
+    '#size' => $element['#size'],
     '#theme_wrappers' => array(),
     '#weight' => -10,
   );
diff --git a/core/modules/file/tests/file.test b/core/modules/file/tests/file.test
index 538118a0f2a46c1a85c63bc04a6cc02e2b975c05..459609b084805c8b06a4dc867c9fdc46c24f8fd2 100644
--- a/core/modules/file/tests/file.test
+++ b/core/modules/file/tests/file.test
@@ -239,6 +239,10 @@ class FileManagedFileElementTestCase extends FileFieldTestCase {
    * Tests the managed_file element type.
    */
   function testManagedFile() {
+    // Check that $element['#size'] is passed to the child upload element.
+    $this->drupalGet('file/test');
+    $this->assertFieldByXpath('//input[@name="files[nested_file]" and @size="13"]', NULL, 'The custom #size attribute is passed to the child upload element.');
+
     // Perform the tests with all permutations of $form['#tree'] and
     // $element['#extended'].
     foreach (array(0, 1) as $tree) {
diff --git a/core/modules/file/tests/file_module_test.module b/core/modules/file/tests/file_module_test.module
index 48ba87b4d91d2bef374c3a14915a892d93f0565c..490ef42991199db1f13f7121dfd1a3eeecd66fd0 100644
--- a/core/modules/file/tests/file_module_test.module
+++ b/core/modules/file/tests/file_module_test.module
@@ -24,8 +24,6 @@ function file_module_test_menu() {
 /**
  * Form constructor for testing a 'managed_file' element.
  *
- * Path: file/test
- *
  * @see file_module_test_menu()
  * @see file_module_test_form_submit()
  * @ingroup forms
@@ -39,6 +37,7 @@ function file_module_test_form($form, &$form_state, $tree = TRUE, $extended = FA
     '#upload_location' => 'public://test',
     '#progress_message' => t('Please wait...'),
     '#extended' => (bool) $extended,
+    '#size' => 13,
   );
   if ($default_fid) {
     $form['nested']['file']['#default_value'] = $extended ? array('fid' => $default_fid) : $default_fid;
diff --git a/core/modules/help/help.admin.inc b/core/modules/help/help.admin.inc
index b37819b9a7dba28a3484c3bbd0b3a25897311174..81cd2244092f5833a3f79daa0f6e46d345a2bf27 100644
--- a/core/modules/help/help.admin.inc
+++ b/core/modules/help/help.admin.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Prints a page listing a glossary of Drupal terminology.
  *
- * Path: admin/help
- *
  * @see help_menu()
  */
 function help_main() {
@@ -22,8 +20,6 @@ function help_main() {
 /**
  * Page callback: Prints a page listing general help for a module.
  *
- * Path: admin/help/%
- *
  * @param $name
  *   A module name to display a help page for.
  *
diff --git a/core/modules/image/image.admin.css b/core/modules/image/image.admin.css
index 3115c8dce97d7c954d9919cf7997bb2d1fb1029c..efe522fc93845d176ccc435206c22d7c4f1be691 100644
--- a/core/modules/image/image.admin.css
+++ b/core/modules/image/image.admin.css
@@ -56,5 +56,5 @@ table.image-anchor tr.odd {
   background: none;
 }
 table.image-anchor td {
-  border: 1px solid #CCC;
+  border: 1px solid #ccc;
 }
diff --git a/core/modules/locale/locale.css b/core/modules/locale/locale.css
index 38112b50607114d61c623257e9a22a739d1502fd..66de82bc98eb0350077dc1b13c938e635c7a0c9f 100644
--- a/core/modules/locale/locale.css
+++ b/core/modules/locale/locale.css
@@ -25,7 +25,7 @@
   padding: 3ex 0 0 1em; /* LTR */
 }
 .language-switcher-locale-session a.active {
-  color: #0062A0;
+  color: #0062a0;
 }
 .language-switcher-locale-session a.session-active {
   color: #000000;
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 4a786bec443bb9a61993fedd7818b665969a5cd3..a785317ab465c6da554f58eb93ac3b39ff6b86bd 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -33,7 +33,7 @@ function locale_help($path, $arg) {
       $output .= '<li>' . t("If an existing translation package does not meet your needs, the Gettext Portable Object (<em>.po</em>) files within a package may be modified, or new <em>.po</em> files may be created, using a desktop Gettext editor. The Locale module's <a href='@import'>import</a> feature allows the translated strings from a new or modified <em>.po</em> file to be added to your site. The Locale module's <a href='@export'>export</a> feature generates files from your site's translated strings, that can either be shared with others or edited offline by a Gettext translation editor.", array('@import' => url('admin/config/regional/translate/import'), '@export' => url('admin/config/regional/translate/export'))) . '</li>';
       $output .= '</ul></dd>';
       $output .= '<dt>' . t('Configuring a multilingual site') . '</dt>';
-      $output .= '<dd>' . t("Language negotiation allows your site to automatically change language based on the domain or path used for each request. Users may (optionally) select their preferred language on their <em>My account</em> page, and your site can be configured to honor a web browser's preferred language settings. Site content can be translated using the <a href='@content-help'>Content translation module</a>.", array('@content-help' => url('admin/help/translation'))) . '</dd>';
+      $output .= '<dd>' . t("Language negotiation allows your site to automatically change language based on the domain or path used for each request. Users may (optionally) select their preferred language on their <em>My account</em> page, and your site can be configured to honor a web browser's preferred language settings. Site content can be translated using the <a href='@content-help'>Content Translation module</a>.", array('@content-help' => url('admin/help/translation'))) . '</dd>';
       $output .= '</dl>';
       return $output;
 
diff --git a/core/modules/node/content_types.inc b/core/modules/node/content_types.inc
index e2440d3d08b355de8815215416a3449337027181..b85cb370eb26eadf041d009dfce31ba5e853dadf 100644
--- a/core/modules/node/content_types.inc
+++ b/core/modules/node/content_types.inc
@@ -8,8 +8,6 @@
 /**
  * Page callback: Displays the content type admin overview page.
  *
- * Path: admin/structure/types
- *
  * @see node_menu()
  */
 function node_overview_types() {
@@ -423,8 +421,6 @@ function node_type_reset($type) {
 /**
  * Page callback: Form constructor for the content type delete form.
  *
- * Path: admin/structure/types/manage/%node_type/delete
- *
  * @param $type
  *   Content type object.
  *
diff --git a/core/modules/node/node.admin.css b/core/modules/node/node.admin.css
new file mode 100644
index 0000000000000000000000000000000000000000..5777b1f15963061355d755805a47e4abb1020815
--- /dev/null
+++ b/core/modules/node/node.admin.css
@@ -0,0 +1,12 @@
+
+/**
+ * @file
+ * Styles for administration pages.
+ */
+
+/**
+ * Revisions overview screen.
+ */
+.revision-current {
+  background: #ffc;
+}
diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc
index 9578417dfeb87ebd4dd393e2a6c66ace725a54b5..1a33174c67cf587933a8bb78ad308479160b59cd 100644
--- a/core/modules/node/node.admin.inc
+++ b/core/modules/node/node.admin.inc
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Query\SelectInterface;
+
 /**
  * @file
  * Content administration and module settings UI.
@@ -8,8 +10,6 @@
 /**
  * Page callback: Form constructor for the permission rebuild confirmation form.
  *
- * Path: admin/reports/status/rebuild
- *
  * @see node_menu()
  * @see node_configure_rebuild_confirm_submit()
  */
@@ -127,7 +127,7 @@ function node_filters() {
  * @param $query
  *   A SelectQuery to which the filters should be applied.
  */
-function node_build_filter_query(SelectQueryInterface $query) {
+function node_build_filter_query(SelectInterface $query) {
   // Build query
   $filter_data = isset($_SESSION['node_overview_filter']) ? $_SESSION['node_overview_filter'] : array();
   foreach ($filter_data as $index => $filter) {
@@ -372,8 +372,6 @@ function _node_mass_update_batch_finished($success, $results, $operations) {
 /**
  * Page callback: Form constructor for the content administration form.
  *
- * Path: admin/content
- *
  * @see node_multiple_delete_confirm()
  * @see node_multiple_delete_confirm_submit()
  * @see node_admin_nodes()
diff --git a/core/modules/node/node.css b/core/modules/node/node.css
deleted file mode 100644
index 07540fa90b94a6138305a7bf573b5a432c662ee5..0000000000000000000000000000000000000000
--- a/core/modules/node/node.css
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.node-unpublished {
-  background-color: #fff4f4;
-}
-.preview .node {
-  background-color: #ffffea;
-}
-td.revision-current {
-  background: #ffc;
-}
diff --git a/core/modules/node/node.info b/core/modules/node/node.info
index 33b5dd2457b14c98bf5da9b5dcf34472b46c2f0e..0e9a3af3b58c51e32e3109864c8b4e29c88f679b 100644
--- a/core/modules/node/node.info
+++ b/core/modules/node/node.info
@@ -7,4 +7,3 @@ files[] = node.module
 files[] = node.test
 dependencies[] = entity
 configure = admin/structure/types
-stylesheets[all][] = node.css
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index efcce1ab36c3c8c42dcfed5325d216ff8f152ed5..b2616ab6b87b6121acaacb402136db8983f652bb 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -18,12 +18,14 @@ function node_schema() {
         'unsigned' => TRUE,
         'not null' => TRUE,
       ),
+      // Defaults to NULL in order to avoid a brief period of potential
+      // deadlocks on the index.
       'vid' => array(
         'description' => 'The current {node_revision}.vid version identifier.',
         'type' => 'int',
         'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
+        'not null' => FALSE,
+        'default' => NULL,
       ),
       'type' => array(
         'description' => 'The {node_type}.type of this node.',
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 5ee9062dcccc5f84f358d982b893c504bf7a9ca9..80d0897d193a6ce7df404109007f3f98920c591c 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1,5 +1,9 @@
 <?php
 
+use Drupal\Core\Database\Query\AlterableInterface;
+use Drupal\Core\Database\Query\SelectExtender;
+use Drupal\Core\Database\Query\SelectInterface;
+
 /**
  * @file
  * The core module that allows content to be submitted to the site.
@@ -603,17 +607,25 @@ function node_add_body_field($type, $label = 'Body') {
  */
 function node_field_extra_fields() {
   $extra = array();
+  $module_language_enabled = module_exists('language');
+  $description = t('Node module element');
+
+  foreach (node_type_get_types() as $bundle) {
+    if ($bundle->has_title) {
+      $extra['node'][$bundle->type]['form']['title'] = array(
+        'label' => $bundle->title_label,
+        'description' => $description,
+        'weight' => -5,
+      );
+    }
 
-  foreach (node_type_get_types() as $type) {
-    if ($type->has_title) {
-      $extra['node'][$type->type] = array(
-        'form' => array(
-          'title' => array(
-            'label' => $type->title_label,
-            'description' => t('Node module element'),
-            'weight' => -5,
-          ),
-        ),
+    // Add also the 'language' select if Language module is enabled and the
+    // bundle has multilingual support.
+    if ($module_language_enabled && variable_get('node_type_language_' . $bundle->type, 0)) {
+      $extra['node'][$bundle->type]['form']['language'] = array(
+        'label' => t('Language'),
+        'description' => $description,
+        'weight' => 0,
       );
     }
   }
@@ -1439,8 +1451,6 @@ function node_build_content($node, $view_mode = 'full', $langcode = NULL) {
 /**
  * Page callback: Generates an array which displays a node detail page.
  *
- * Path: node/%node/revisions/%/view
- *
  * @param $node
  *   A node object.
  * @param $message
@@ -1559,19 +1569,19 @@ function template_preprocess_node(&$variables) {
   // Gather node classes.
   $variables['classes_array'][] = drupal_html_class('node-' . $node->type);
   if ($variables['promote']) {
-    $variables['classes_array'][] = 'node-promoted';
+    $variables['classes_array'][] = 'promoted';
   }
   if ($variables['sticky']) {
-    $variables['classes_array'][] = 'node-sticky';
+    $variables['classes_array'][] = 'sticky';
   }
   if (!$variables['status']) {
-    $variables['classes_array'][] = 'node-unpublished';
+    $variables['classes_array'][] = 'unpublished';
   }
-  if ($variables['teaser']) {
-    $variables['classes_array'][] = 'node-teaser';
+  if ($variables['view_mode']) {
+    $variables['classes_array'][] = drupal_html_class('view-mode-' . $variables['view_mode']);
   }
   if (isset($variables['preview'])) {
-    $variables['classes_array'][] = 'node-preview';
+    $variables['classes_array'][] = 'preview';
   }
 
   // Clean up name so there are no underscores.
@@ -1631,7 +1641,7 @@ function node_permission() {
  * @param $query
  *   A query object that has been extended with the Search DB Extender.
  */
-function _node_rankings(SelectQueryExtender $query) {
+function _node_rankings(SelectExtender $query) {
   if ($ranking = module_invoke_all('ranking')) {
     $tables = &$query->getTables();
     foreach ($ranking as $rank => $values) {
@@ -1898,12 +1908,6 @@ function theme_node_search_admin($variables) {
 /**
  * Access callback: Checks node revision access.
  *
- * Paths:
- * - node/%node/revisions
- * - node/%node/revisions/%/view
- * - node/%node/revisions/%/revert
- * - node/%node/revisions/%/delete
- *
  * @param $node
  *   The node to check.
  * @param $op
@@ -1951,8 +1955,6 @@ function _node_revision_access($node, $op = 'view') {
 /**
  * Access callback: Checks whether the user has permission to add a node.
  *
- * Paths: node/add
- *
  * @return
  *   TRUE if the user has permission, otherwise FALSE.
  *
@@ -2174,8 +2176,6 @@ function node_menu_local_tasks_alter(&$data, $router_item, $root_path) {
 /**
  * Title callback: Provides the title for a node type edit form.
  *
- * Path: admin/structure/types/manage/%node_type
- *
  * @param $type
  *   The node type object.
  *
@@ -2188,8 +2188,6 @@ function node_type_page_title($type) {
 /**
  * Title callback: Displays the node's title.
  *
- * Path: node/%node
- *
  * @param $node
  *   The node object.
  *
@@ -2554,8 +2552,6 @@ function node_block_list_alter(&$blocks) {
 /**
  * Page callback: Generates and prints an RSS feed.
  *
- * Path: rss.xml
- *
  * Generates an RSS feed from an array of node IDs, and prints it with an HTTP
  * header, with Content Type set to RSS/XML.
  *
@@ -2674,8 +2670,6 @@ function node_view_multiple($nodes, $view_mode = 'teaser', $weight = 0, $langcod
 /**
  * Page callback: Generates a listing of promoted nodes.
  *
- * Path: node
- *
  * @see node_menu()
  */
 function node_page_default() {
@@ -2728,8 +2722,6 @@ function node_page_default() {
 /**
  * Page callback: Displays a single node.
  *
- * Path: node/%node
- *
  * @param $node
  *   The node object.
  *
@@ -2980,12 +2972,6 @@ function node_form_system_themes_admin_form_submit($form, &$form_state) {
 /**
  * Access callback: Checks a user's permission for performing a node operation.
  *
- * Paths:
- * - node/%node
- * - node/%node/edit
- * - node/%node/delete
- * - 'node/add/' . $type_url_str (part of foreach)
- *
  * @param $op
  *   The operation to be performed on the node. Possible values are:
  *   - "view"
@@ -3299,7 +3285,7 @@ function node_access_view_all_nodes($account = NULL) {
  * the 'op' meta-data (or 'view' if not provided; other possible values are
  * 'update' and 'delete').
  */
-function node_query_node_access_alter(QueryAlterableInterface $query) {
+function node_query_node_access_alter(AlterableInterface $query) {
   _node_query_node_access_alter($query, 'node');
 }
 
@@ -3310,7 +3296,7 @@ function node_query_node_access_alter(QueryAlterableInterface $query) {
  * node_query_node_access_alter() for the SQL field storage engine. Node access
  * conditions are added for field values belonging to nodes only.
  */
-function node_query_entity_field_access_alter(QueryAlterableInterface $query) {
+function node_query_entity_field_access_alter(AlterableInterface $query) {
   _node_query_node_access_alter($query, 'entity');
 }
 
@@ -3354,7 +3340,7 @@ function _node_query_node_access_alter($query, $type) {
   if (!$base_table) {
     $fallback = '';
     foreach ($tables as $alias => $table_info) {
-      if (!($table_info instanceof SelectQueryInterface)) {
+      if (!($table_info instanceof SelectInterface)) {
         $table = $table_info['table'];
         // If the node table is in the query, it wins immediately.
         if ($table == 'node') {
@@ -3426,7 +3412,7 @@ function _node_query_node_access_alter($query, $type) {
   }
   foreach ($tables as $nalias => $tableinfo) {
     $table = $tableinfo['table'];
-    if (!($table instanceof SelectQueryInterface) && $table == $base_table) {
+    if (!($table instanceof SelectInterface) && $table == $base_table) {
 
       // The node_access table has the access grants for any given node so JOIN
       // it to the table containing the nid which can be either the node
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index 95e2e7dc9c3c91763f9b4c225514bf52da578a27..34a8d4f3be9c8123c1dc83ecb874ef1307fac31a 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -13,8 +13,6 @@
 /**
  * Page callback: Presents the node editing form.
  *
- * Path: node/%node/edit
- *
  * @see node_menu()
  */
 function node_page_edit($node) {
@@ -26,8 +24,6 @@ function node_page_edit($node) {
 /**
  * Page callback: Presents the node add form.
  *
- * Path: node/add
- *
  * @see node_menu()
  */
 function node_add_page() {
@@ -73,8 +69,6 @@ function theme_node_add_list($variables) {
 /**
  * Page callback: Provides the node submission form.
  *
- * Path: 'node/add/' . $type_url_str (part of a foreach)
- *
  * @param $type
  *   The node type for the submitted node.
  *
@@ -455,7 +449,7 @@ function node_preview($node) {
 function theme_node_preview($variables) {
   $node = $variables['node'];
 
-  $output = '<div class="preview">';
+  $output = '';
 
   $preview_trimmed_version = FALSE;
 
@@ -475,7 +469,6 @@ function theme_node_preview($variables) {
   else {
     $output .= $full;
   }
-  $output .= "</div>\n";
 
   return $output;
 }
@@ -559,8 +552,6 @@ function node_form_submit_build_node($form, &$form_state) {
 /**
  * Page callback: Form constructor for node deletion confirmation form.
  *
- * Path: node/%node/delete
- *
  * @see node_menu()
  */
 function node_delete_confirm($form, &$form_state, $node) {
@@ -593,8 +584,6 @@ function node_delete_confirm_submit($form, &$form_state) {
 /**
  * Page callback: Generates an overview table of older revisions of a node.
  *
- * Path: node/%node/revisions
- *
  * @see node_menu()
  */
 function node_revision_overview($node) {
@@ -640,6 +629,9 @@ function node_revision_overview($node) {
     '#theme' => 'table',
     '#rows' => $rows,
     '#header' => $header,
+    '#attached' => array (
+      'css' => array(drupal_get_path('module', 'node') . '/node.admin.css'),
+    ),
   );
 
   return $build;
@@ -648,8 +640,6 @@ function node_revision_overview($node) {
 /**
  * Page callback: Form constructor for the reversion confirmation form.
  *
- * Path: node/%node/revisions/%/revert
- *
  * This form prevents against CSRF attacks.
  *
  * @see node_menu()
@@ -678,8 +668,6 @@ function node_revision_revert_confirm_submit($form, &$form_state) {
 /**
  * Page callback: Form constructor for the revision deletion confirmation form.
  *
- * Path: node/%node/revisions/%/delete
- *
  * This form prevents against CSRF attacks.
  *
  * @see node_menu()
diff --git a/core/modules/node/node.test b/core/modules/node/node.test
index 02001c713f29f2a658eb3c530d36fdd10c3aa19f..96d4e01e340cf7206de3bec2d132293667f2119a 100644
--- a/core/modules/node/node.test
+++ b/core/modules/node/node.test
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * @file
  * Tests for node.module.
diff --git a/core/modules/node/node.tpl.php b/core/modules/node/node.tpl.php
index adb9aa2f65473e78ee8fe30da9690e9bb07d5f5a..a251ecc6c038ff8cba550fd394d4f8f683f6aef4 100644
--- a/core/modules/node/node.tpl.php
+++ b/core/modules/node/node.tpl.php
@@ -26,13 +26,13 @@
  *   - node-[type]: The current node type. For example, if the node is a
  *     "Article" it would result in "node-article". Note that the machine
  *     name will often be in a short form of the human readable label.
- *   - node-teaser: Nodes in teaser form.
- *   - node-preview: Nodes in preview mode.
+ *   - view-mode-[view_mode]: The View Mode of the node e.g. teaser or full.
+ *   - preview: Nodes in preview mode.
  *   The following are controlled through the node publishing options.
- *   - node-promoted: Nodes promoted to the front page.
- *   - node-sticky: Nodes ordered above other non-sticky nodes in teaser
+ *   - promoted: Nodes promoted to the front page.
+ *   - sticky: Nodes ordered above other non-sticky nodes in teaser
  *     listings.
- *   - node-unpublished: Unpublished nodes visible only to administrators.
+ *   - unpublished: Unpublished nodes visible only to administrators.
  * - $title_prefix (array): An array containing additional output populated by
  *   modules, intended to be displayed in front of the main title tag that
  *   appears in the template.
diff --git a/core/modules/node/tests/node_access_test.module b/core/modules/node/tests/node_access_test.module
index c17f07ebf6d86b3625227f0015c5e4eaae5caa24..c1e7edda14763959109f6e30ed5d3329acfdb7e9 100644
--- a/core/modules/node/tests/node_access_test.module
+++ b/core/modules/node/tests/node_access_test.module
@@ -87,8 +87,6 @@ function node_access_test_menu() {
 /**
  * Page callback: Creates the node access test page.
  *
- * Path: node_access_test_page
- *
  * Page should say "No nodes" if there are no nodes, and "Yes, # nodes" (with
  * the number filled in) if there were nodes the user could access. Also, the
  * database query is shown, and a list of the node IDs, for debugging purposes.
@@ -131,8 +129,6 @@ function node_access_test_page() {
 /**
  * Page callback: Creates the node access entity test page.
  *
- * Path: node_access_entity_test_page
- *
  * Page should say "No nodes" if there are no nodes, and "Yes, # nodes" (with
  * the number filled in) if there were nodes the user could access. Also, the
  * database query is shown, and a list of the node IDs, for debugging purposes.
diff --git a/core/modules/php/php.info b/core/modules/php/php.info
index 669a138f8f448bce7983792a99cb205b06f5d811..e1f2d570d52470045ada4db1fdfed2b52cc1d160 100644
--- a/core/modules/php/php.info
+++ b/core/modules/php/php.info
@@ -1,4 +1,4 @@
-name = PHP filter
+name = PHP Filter
 description = Allows embedded PHP code/snippets to be evaluated.
 package = Core
 version = VERSION
diff --git a/core/modules/php/php.module b/core/modules/php/php.module
index 1fb91c10bcfa94e06fd863436ade5bac7bd4d3f5..6e295d79359dccbb8b3db45d9d2ce82c3b3b09a9 100644
--- a/core/modules/php/php.module
+++ b/core/modules/php/php.module
@@ -13,11 +13,11 @@ function php_help($path, $arg) {
     case 'admin/help#php':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('The PHP filter module adds a PHP filter to your site, for use with <a href="@filter">text formats</a>. This filter adds the ability to execute PHP code in any text field that uses a text format (such as the body of a content item or the text of a comment). <a href="@php-net">PHP</a> is a general-purpose scripting language widely-used for web development, and is the language with which Drupal has been developed. For more information, see the online handbook entry for the <a href="@php">PHP filter module</a>.', array('@filter' => url('admin/help/filter'), '@php-net' => 'http://www.php.net', '@php' => 'http://drupal.org/handbook/modules/php/')) . '</p>';
+      $output .= '<p>' . t('The PHP Filter module adds a PHP filter to your site, for use with <a href="@filter">text formats</a>. This filter adds the ability to execute PHP code in any text field that uses a text format (such as the body of a content item or the text of a comment). <a href="@php-net">PHP</a> is a general-purpose scripting language widely-used for web development, and is the language with which Drupal has been developed. For more information, see the online handbook entry for the <a href="@php">PHP Filter module</a>.', array('@filter' => url('admin/help/filter'), '@php-net' => 'http://www.php.net', '@php' => 'http://drupal.org/handbook/modules/php/')) . '</p>';
       $output .= '<h3>' . t('Uses') . '</h3>';
       $output .= '<dl>';
       $output .= '<dt>' . t('Enabling execution of PHP in text fields') . '</dt>';
-      $output .= '<dd>' . t('The PHP filter module allows users with the proper permissions to include custom PHP code that will get executed when pages of your site are processed. While this is a powerful and flexible feature if used by a trusted user with PHP experience, it is a significant and dangerous security risk in the hands of a malicious or inexperienced user. Even a trusted user may accidentally compromise the site by entering malformed or incorrect PHP code. Only the most trusted users should be granted permission to use the PHP filter, and all PHP code added through the PHP filter should be carefully examined before use. <a href="@php-snippets">Example PHP snippets</a> can be found on Drupal.org.', array('@php-snippets' => url('http://drupal.org/handbook/customization/php-snippets'))) . '</dd>';
+      $output .= '<dd>' . t('The PHP Filter module allows users with the proper permissions to include custom PHP code that will get executed when pages of your site are processed. While this is a powerful and flexible feature if used by a trusted user with PHP experience, it is a significant and dangerous security risk in the hands of a malicious or inexperienced user. Even a trusted user may accidentally compromise the site by entering malformed or incorrect PHP code. Only the most trusted users should be granted permission to use the PHP filter, and all PHP code added through the PHP filter should be carefully examined before use. <a href="@php-snippets">Example PHP snippets</a> can be found on Drupal.org.', array('@php-snippets' => url('http://drupal.org/handbook/customization/php-snippets'))) . '</dd>';
       $output .= '</dl>';
       return $output;
   }
diff --git a/core/modules/search/search.extender.inc b/core/modules/search/search.extender.inc
index ad4b86e896137799cb0ed2dddf4af1e85c47f1e7..73f783652f6dba592d189337d45e5d4496915535 100644
--- a/core/modules/search/search.extender.inc
+++ b/core/modules/search/search.extender.inc
@@ -1,5 +1,8 @@
 <?php
 
+use Drupal\Core\Database\Query\SelectExtender;
+use Drupal\Core\Database\StatementEmpty;
+
 /**
  * @file
  * Search query extender and helper functions.
@@ -24,7 +27,7 @@
  * The used query object has the tag 'search_$module' and can be further
  * extended with hook_query_alter().
  */
-class SearchQuery extends SelectQueryExtender {
+class SearchQuery extends SelectExtender {
   /**
    * The search query that is used for searching.
    *
@@ -433,7 +436,7 @@ public function execute()
       $this->executeFirstPass();
     }
     if (!$this->normalize) {
-      return new DatabaseStatementEmpty();
+      return new StatementEmpty();
     }
 
     // Add conditions to query.
diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php
index 61e54df193d18611216740de99339536f1880764..c82d3b14ccba6bbaf76fb02d7d1676b77bef08c9 100644
--- a/core/modules/simpletest/drupal_web_test_case.php
+++ b/core/modules/simpletest/drupal_web_test_case.php
@@ -1,5 +1,8 @@
 <?php
 
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\ConnectionNotDefinedException;
+
 /**
  * Global variable that holds information about the tests being run.
  *
@@ -152,7 +155,7 @@ protected function assert($status, $message = '', $group = 'Other', array $calle
     try {
       $connection = Database::getConnection('default', 'simpletest_original_default');
     }
-    catch (DatabaseConnectionNotDefinedException $e) {
+    catch (ConnectionNotDefinedException $e) {
       // If the test was not set up, the simpletest_original_default
       // connection does not exist.
       $connection = Database::getConnection('default', 'default');
diff --git a/core/modules/simpletest/files/css_test_files/comment_hacks.css b/core/modules/simpletest/files/css_test_files/comment_hacks.css
index c47e8429ac27c898d1711a849373e42c6111d2f7..8b12d6cb977a833115f5e2ae384fe47ba8f2e25f 100644
--- a/core/modules/simpletest/files/css_test_files/comment_hacks.css
+++ b/core/modules/simpletest/files/css_test_files/comment_hacks.css
@@ -22,7 +22,7 @@ html .clear-block {
 
 /* v1 of the commented backslash hack. This \ character between rules appears to have the effect
 that macIE5 ignores the following rule. Odd, but extremely useful. */
-.bkslshv1 { background-color: #C00; }
+.bkslshv1 { background-color: #c00; }
 .test3 { display:block; }
 
 /**************** A multiline, multistar comment ***************
@@ -34,8 +34,8 @@ that macIE5 ignores the following rule. Odd, but extremely useful. */
   content: "/* ";
 }
 .this_rule_must_stay {
-  color: #F00;
-  background-color: #FFF;
+  color: #f00;
+  background-color: #fff;
 }
 .comment-in-double-quotes:after {
   content: " */";
@@ -45,8 +45,8 @@ that macIE5 ignores the following rule. Odd, but extremely useful. */
   content: '/*';
 }
 .this_rule_must_stay {
-  color: #F00;
-  background-color: #FFF;
+  color: #f00;
+  background-color: #fff;
 }
 .comment-in-single-quotes:after {
   content: '*/';
@@ -56,8 +56,8 @@ that macIE5 ignores the following rule. Odd, but extremely useful. */
   content: '"/*"';
 }
 .this_rule_must_stay {
-  color: #F00;
-  background-color: #FFF;
+  color: #f00;
+  background-color: #fff;
 }
 .comment-in-mixed-quotes:after {
   content: "'*/'";
@@ -67,8 +67,8 @@ that macIE5 ignores the following rule. Odd, but extremely useful. */
   content: '/* \" \' */';
 }
 .this_rule_must_stay {
-  color: #F00;
-  background-color: #FFF;
+  color: #f00;
+  background-color: #fff;
 }
 .comment-in-quotes-with-escaped:after {
   content: "*/ \" \ '";
diff --git a/core/modules/simpletest/files/css_test_files/comment_hacks.css.optimized.css b/core/modules/simpletest/files/css_test_files/comment_hacks.css.optimized.css
index 1feb8f1bd7d36e7402c1803278b857233f82a1c0..4e6615adb64cb32d2f905cb10946b2a603316110 100644
--- a/core/modules/simpletest/files/css_test_files/comment_hacks.css.optimized.css
+++ b/core/modules/simpletest/files/css_test_files/comment_hacks.css.optimized.css
@@ -1 +1 @@
-.test1{display:block;}html .clear-block{height:1%;}.clear-block{display:block;font:italic bold 12px/30px Georgia,serif;}.test2{display:block;}.bkslshv1{background-color:#C00;}.test3{display:block;}.test4{display:block;}.comment-in-double-quotes:before{content:"/* ";}.this_rule_must_stay{color:#F00;background-color:#FFF;}.comment-in-double-quotes:after{content:" */";}.comment-in-single-quotes:before{content:'/*';}.this_rule_must_stay{color:#F00;background-color:#FFF;}.comment-in-single-quotes:after{content:'*/';}.comment-in-mixed-quotes:before{content:'"/*"';}.this_rule_must_stay{color:#F00;background-color:#FFF;}.comment-in-mixed-quotes:after{content:"'*/'";}.comment-in-quotes-with-escaped:before{content:'/* \" \' */';}.this_rule_must_stay{color:#F00;background-color:#FFF;}.comment-in-quotes-with-escaped:after{content:"*/ \" \ '";}
+.test1{display:block;}html .clear-block{height:1%;}.clear-block{display:block;font:italic bold 12px/30px Georgia,serif;}.test2{display:block;}.bkslshv1{background-color:#c00;}.test3{display:block;}.test4{display:block;}.comment-in-double-quotes:before{content:"/* ";}.this_rule_must_stay{color:#f00;background-color:#fff;}.comment-in-double-quotes:after{content:" */";}.comment-in-single-quotes:before{content:'/*';}.this_rule_must_stay{color:#f00;background-color:#fff;}.comment-in-single-quotes:after{content:'*/';}.comment-in-mixed-quotes:before{content:'"/*"';}.this_rule_must_stay{color:#f00;background-color:#fff;}.comment-in-mixed-quotes:after{content:"'*/'";}.comment-in-quotes-with-escaped:before{content:'/* \" \' */';}.this_rule_must_stay{color:#f00;background-color:#fff;}.comment-in-quotes-with-escaped:after{content:"*/ \" \ '";}
diff --git a/core/modules/simpletest/files/css_test_files/comment_hacks.css.unoptimized.css b/core/modules/simpletest/files/css_test_files/comment_hacks.css.unoptimized.css
index c47e8429ac27c898d1711a849373e42c6111d2f7..8b12d6cb977a833115f5e2ae384fe47ba8f2e25f 100644
--- a/core/modules/simpletest/files/css_test_files/comment_hacks.css.unoptimized.css
+++ b/core/modules/simpletest/files/css_test_files/comment_hacks.css.unoptimized.css
@@ -22,7 +22,7 @@ html .clear-block {
 
 /* v1 of the commented backslash hack. This \ character between rules appears to have the effect
 that macIE5 ignores the following rule. Odd, but extremely useful. */
-.bkslshv1 { background-color: #C00; }
+.bkslshv1 { background-color: #c00; }
 .test3 { display:block; }
 
 /**************** A multiline, multistar comment ***************
@@ -34,8 +34,8 @@ that macIE5 ignores the following rule. Odd, but extremely useful. */
   content: "/* ";
 }
 .this_rule_must_stay {
-  color: #F00;
-  background-color: #FFF;
+  color: #f00;
+  background-color: #fff;
 }
 .comment-in-double-quotes:after {
   content: " */";
@@ -45,8 +45,8 @@ that macIE5 ignores the following rule. Odd, but extremely useful. */
   content: '/*';
 }
 .this_rule_must_stay {
-  color: #F00;
-  background-color: #FFF;
+  color: #f00;
+  background-color: #fff;
 }
 .comment-in-single-quotes:after {
   content: '*/';
@@ -56,8 +56,8 @@ that macIE5 ignores the following rule. Odd, but extremely useful. */
   content: '"/*"';
 }
 .this_rule_must_stay {
-  color: #F00;
-  background-color: #FFF;
+  color: #f00;
+  background-color: #fff;
 }
 .comment-in-mixed-quotes:after {
   content: "'*/'";
@@ -67,8 +67,8 @@ that macIE5 ignores the following rule. Odd, but extremely useful. */
   content: '/* \" \' */';
 }
 .this_rule_must_stay {
-  color: #F00;
-  background-color: #FFF;
+  color: #f00;
+  background-color: #fff;
 }
 .comment-in-quotes-with-escaped:after {
   content: "*/ \" \ '";
diff --git a/core/modules/simpletest/simpletest.css b/core/modules/simpletest/simpletest.css
index 0cf9aaa5edd07829490c487df9146f655779eeb8..86bd04b07869ac4d896749cfca09017d507bd037 100644
--- a/core/modules/simpletest/simpletest.css
+++ b/core/modules/simpletest/simpletest.css
@@ -27,7 +27,7 @@ th.simpletest_test {
   color: #494949;
 }
 #simpletest-form-table tr.simpletest-group td {
-  background-color: #EDF5FA;
+  background-color: #edf5fa;
   color: #494949;
 }
 
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index 831ea859ec5c1d64f1513d6fc434fb0b78ca8cd4..080b621b3b7b2a4ff9c370a598efe793a7faac7a 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * @file
  * Provides testing functionality.
diff --git a/core/modules/simpletest/tests/common.test b/core/modules/simpletest/tests/common.test
index 1c9a7e7d324a31bc3ba17e352fd85f2ccefdf643..eeb5e497f6d2305756f35a89f0b33ac68b4ef44d 100644
--- a/core/modules/simpletest/tests/common.test
+++ b/core/modules/simpletest/tests/common.test
@@ -806,7 +806,7 @@ class CommonCascadingStylesheetsTestCase extends DrupalWebTestCase {
   function testAddCssFileWithQueryString() {
     $this->drupalGet('common-test/query-string');
     $query_string = variable_get('css_js_query_string', '0');
-    $this->assertRaw(drupal_get_path('module', 'node') . '/node.css?' . $query_string, t('Query string was appended correctly to css.'));
+    $this->assertRaw(drupal_get_path('module', 'node') . '/node.admin.css?' . $query_string, t('Query string was appended correctly to css.'));
     $this->assertRaw(drupal_get_path('module', 'node') . '/node-fake.css?arg1=value1&amp;arg2=value2', t('Query string not escaped on a URI.'));
   }
 }
diff --git a/core/modules/simpletest/tests/common_test.module b/core/modules/simpletest/tests/common_test.module
index e1cfdf288a473dbe438728725ac35321c194eb35..187fee55b06d2ad5f15a2b19cc0d619ad88171ab 100644
--- a/core/modules/simpletest/tests/common_test.module
+++ b/core/modules/simpletest/tests/common_test.module
@@ -270,7 +270,7 @@ function common_test_library_info() {
  */
 function common_test_js_and_css_querystring() {
    drupal_add_js(drupal_get_path('module', 'node') . '/node.js');
-   drupal_add_css(drupal_get_path('module', 'node') . '/node.css');
+   drupal_add_css(drupal_get_path('module', 'node') . '/node.admin.css');
    // A relative URI may have a query string.
    drupal_add_css('/' . drupal_get_path('module', 'node') . '/node-fake.css?arg1=value1&arg2=value2');
    return '';
diff --git a/core/modules/simpletest/tests/database_test.module b/core/modules/simpletest/tests/database_test.module
index 6fac31919c7362d950415cb6f1ddefa6941c15fd..0ab51d80747ac345162d2eb9fd925ea770b1062d 100644
--- a/core/modules/simpletest/tests/database_test.module
+++ b/core/modules/simpletest/tests/database_test.module
@@ -1,9 +1,11 @@
 <?php
 
+use Drupal\Core\Database\Query\AlterableInterface;
+
 /**
  * Implements hook_query_alter().
  */
-function database_test_query_alter(QueryAlterableInterface $query) {
+function database_test_query_alter(AlterableInterface $query) {
 
   if ($query->hasTag('database_test_alter_add_range')) {
     $query->range(0, 2);
@@ -37,7 +39,7 @@ function database_test_query_alter(QueryAlterableInterface $query) {
  *
  * Called by DatabaseTestCase::testAlterRemoveRange.
  */
-function database_test_query_database_test_alter_remove_range_alter(QueryAlterableInterface $query) {
+function database_test_query_database_test_alter_remove_range_alter(AlterableInterface $query) {
   $query->range();
 }
 
diff --git a/core/modules/simpletest/tests/database_test.test b/core/modules/simpletest/tests/database_test.test
index 16c09c654c4fb3e9257bba878d0da10ce885ef1a..1d38ebb3766bef2aa2bf2bfe3f917be89f936238 100644
--- a/core/modules/simpletest/tests/database_test.test
+++ b/core/modules/simpletest/tests/database_test.test
@@ -1,5 +1,14 @@
 <?php
 
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\StatementEmpty;
+use Drupal\Core\Database\StatementInterface;
+use Drupal\Core\Database\TransactionOutOfOrderException;
+use Drupal\Core\Database\TransactionNoActiveException;
+use Drupal\Core\Database\Query\Merge;
+use Drupal\Core\Database\Query\InvalidMergeQueryException;
+use Drupal\Core\Database\Query\NoFieldsException;
+
 /**
  * Dummy class for fetching into a class.
  *
@@ -307,7 +316,7 @@ class DatabaseFetchTestCase extends DatabaseTestCase {
   function testQueryFetchDefault() {
     $records = array();
     $result = db_query('SELECT name FROM {test} WHERE age = :age', array(':age' => 25));
-    $this->assertTrue($result instanceof DatabaseStatementInterface, t('Result set is a Drupal statement object.'));
+    $this->assertTrue($result instanceof StatementInterface, t('Result set is a Drupal statement object.'));
     foreach ($result as $record) {
       $records[] = $record;
       $this->assertTrue(is_object($record), t('Record is an object.'));
@@ -1090,7 +1099,7 @@ class DatabaseMergeTestCase extends DatabaseTestCase {
       ))
       ->execute();
 
-    $this->assertEqual($result, MergeQuery::STATUS_INSERT, t('Insert status returned.'));
+    $this->assertEqual($result, Merge::STATUS_INSERT, t('Insert status returned.'));
 
     $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
     $this->assertEqual($num_records_before + 1, $num_records_after, t('Merge inserted properly.'));
@@ -1115,7 +1124,7 @@ class DatabaseMergeTestCase extends DatabaseTestCase {
       ))
       ->execute();
 
-    $this->assertEqual($result, MergeQuery::STATUS_UPDATE, t('Update status returned.'));
+    $this->assertEqual($result, Merge::STATUS_UPDATE, t('Update status returned.'));
 
     $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
     $this->assertEqual($num_records_before, $num_records_after, t('Merge updated properly.'));
@@ -3512,7 +3521,7 @@ class DatabaseTransactionTestCase extends DatabaseTestCase {
         // "ROLLBACK" fails silently in MySQL if there is no transaction active.
         // $this->fail(t('Rolling back a transaction containing DDL should fail.'));
       }
-      catch (DatabaseTransactionNoActiveException $e) {
+      catch (TransactionNoActiveException $e) {
         $this->pass(t('Rolling back a transaction containing DDL should fail.'));
       }
       $this->assertRowPresent('row');
@@ -3680,7 +3689,7 @@ class DatabaseTransactionTestCase extends DatabaseTestCase {
       unset($transaction);
       $this->fail(t('Rolling back the outer transaction while the inner transaction is active resulted in an exception.'));
     }
-    catch (DatabaseTransactionOutOfOrderException $e) {
+    catch (TransactionOutOfOrderException $e) {
       $this->pass(t('Rolling back the outer transaction while the inner transaction is active resulted in an exception.'));
     }
     $this->assertFalse($database->inTransaction(), t('No more in a transaction after rolling back the outer transaction'));
@@ -3693,7 +3702,7 @@ class DatabaseTransactionTestCase extends DatabaseTestCase {
       unset($transaction2);
       $this->fail(t('Trying to commit an inner transaction resulted in an exception.'));
     }
-    catch (DatabaseTransactionNoActiveException $e) {
+    catch (TransactionNoActiveException $e) {
       $this->pass(t('Trying to commit an inner transaction resulted in an exception.'));
     }
     $this->assertRowAbsent('outer');
@@ -3746,9 +3755,9 @@ class DatabaseEmptyStatementTestCase extends DrupalWebTestCase {
    * Test that the empty result set behaves as empty.
    */
   function testEmpty() {
-    $result = new DatabaseStatementEmpty();
+    $result = new StatementEmpty();
 
-    $this->assertTrue($result instanceof DatabaseStatementInterface, t('Class implements expected interface'));
+    $this->assertTrue($result instanceof StatementInterface, t('Class implements expected interface'));
     $this->assertNull($result->fetchObject(), t('Null result returned.'));
   }
 
@@ -3756,7 +3765,7 @@ class DatabaseEmptyStatementTestCase extends DrupalWebTestCase {
    * Test that the empty result set iterates safely.
    */
   function testEmptyIteration() {
-    $result = new DatabaseStatementEmpty();
+    $result = new StatementEmpty();
 
     foreach ($result as $record) {
       $this->fail(t('Iterating empty result set should not iterate.'));
@@ -3770,7 +3779,7 @@ class DatabaseEmptyStatementTestCase extends DrupalWebTestCase {
    * Test that the empty result set mass-fetches in an expected way.
    */
   function testEmptyFetchAll() {
-    $result = new DatabaseStatementEmpty();
+    $result = new StatementEmpty();
 
     $this->assertEqual($result->fetchAll(), array(), t('Empty array returned from empty result set.'));
   }
diff --git a/core/modules/simpletest/tests/form.test b/core/modules/simpletest/tests/form.test
index 784da8849c9bae81542554339612c1217aa85810..6e40f1f9fc6165beaa6a3f3fd706e64ccae8f666 100644
--- a/core/modules/simpletest/tests/form.test
+++ b/core/modules/simpletest/tests/form.test
@@ -261,7 +261,7 @@ class FormsTestCase extends DrupalWebTestCase {
 
     // All the elements should be marked as disabled, including the ones below
     // the disabled container.
-    $this->assertEqual(count($disabled_elements), 33, t('The correct elements have the disabled property in the HTML code.'));
+    $this->assertEqual(count($disabled_elements), 34, t('The correct elements have the disabled property in the HTML code.'));
 
     $this->drupalPost(NULL, $edit, t('Submit'));
     $returned_values['hijacked'] = drupal_json_decode($this->content);
@@ -390,14 +390,13 @@ class FormElementTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Tests placeholder text for textfield, password, and textarea.
+   * Tests placeholder text for elements that support placeholders.
    */
   function testPlaceHolderText() {
     $this->drupalGet('form-test/placeholder-text');
     $expected = 'placeholder-text';
-    // Test to make sure textfields and passwords have the proper placeholder
-    // text.
-    foreach (array('textfield', 'password') as $type) {
+    // Test to make sure non-textarea elements have the proper placeholder text.
+    foreach (array('textfield', 'tel', 'password') as $type) {
       $element = $this->xpath('//input[@id=:id and @placeholder=:expected]', array(
         ':id' => 'edit-' . $type,
         ':expected' => $expected,
diff --git a/core/modules/simpletest/tests/form_test.module b/core/modules/simpletest/tests/form_test.module
index a2f1290cbf0c4560fa8772e6b130c4ed8fecfd30..76e5c260de3d62ce449ff21140cedb44c2c38acf 100644
--- a/core/modules/simpletest/tests/form_test.module
+++ b/core/modules/simpletest/tests/form_test.module
@@ -1196,7 +1196,7 @@ function _form_test_disabled_elements($form, &$form_state) {
   $form['disabled_container'] = array(
     '#disabled' => TRUE,
   );
-  foreach (array('textfield', 'textarea', 'hidden') as $type) {
+  foreach (array('textfield', 'textarea', 'hidden', 'tel') as $type) {
     $form['disabled_container']['disabled_container_' . $type] = array(
       '#type' => $type,
       '#title' => $type,
diff --git a/core/modules/simpletest/tests/schema.test b/core/modules/simpletest/tests/schema.test
index 8945117cbbdba4b13b70f9fd50ffbb4fce8a1460..5a105678fc7c9845032b994e787ef83138dbcb57 100644
--- a/core/modules/simpletest/tests/schema.test
+++ b/core/modules/simpletest/tests/schema.test
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * @file
  * Tests for the Database Schema API.
diff --git a/core/modules/simpletest/tests/upgrade/upgrade.test b/core/modules/simpletest/tests/upgrade/upgrade.test
index 381816c72e84485f26a6e47b9c5714aa87dd045f..aafb642cfd4799a40b2a011358b79a8698360025 100644
--- a/core/modules/simpletest/tests/upgrade/upgrade.test
+++ b/core/modules/simpletest/tests/upgrade/upgrade.test
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * Perform end-to-end tests of the upgrade path.
  */
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module
index eda808faaac6fd7cb6f1d59b8b2f8002d2aa31bc..969a4f4f82d5b4cd02d4afdd585a0b444652d810 100644
--- a/core/modules/statistics/statistics.module
+++ b/core/modules/statistics/statistics.module
@@ -119,7 +119,7 @@ function statistics_node_view($node, $view_mode) {
     if (user_access('view post access counter')) {
       $statistics = statistics_get($node->nid);
       if ($statistics) {
-        $links['statistics_counter']['title'] = format_plural($statistics['totalcount'], '1 read', '@count reads');
+        $links['statistics_counter']['title'] = format_plural($statistics['totalcount'], '1 view', '@count views');
         $node->content['links']['statistics'] = array(
           '#theme' => 'links__node__statistics',
           '#links' => $links,
diff --git a/core/modules/statistics/statistics.test b/core/modules/statistics/statistics.test
index d710af258d7fbc2e51604644ac42f380099a245b..bf3aeac4cb202ecb55dbbe879cfb69adf8dec6bf 100644
--- a/core/modules/statistics/statistics.test
+++ b/core/modules/statistics/statistics.test
@@ -329,12 +329,12 @@ class StatisticsAdminTestCase extends DrupalWebTestCase {
     $this->assertText('node/1', t('Test node found.'));
 
     // Hit the node again (the counter is incremented after the hit, so
-    // "1 read" will actually be shown when the node is hit the second time).
+    // "1 view" will actually be shown when the node is hit the second time).
     $this->drupalGet('node/' . $this->test_node->nid);
-    $this->assertText('1 read', t('Node is read once.'));
+    $this->assertText('1 view', t('Node is viewed once.'));
 
     $this->drupalGet('node/' . $this->test_node->nid);
-    $this->assertText('2 reads', t('Node is read 2 times.'));
+    $this->assertText('2 views', t('Node is viewed 2 times.'));
   }
 
   /**
@@ -400,7 +400,7 @@ class StatisticsAdminTestCase extends DrupalWebTestCase {
 
     $this->drupalGet('node/' . $this->test_node->nid);
     $this->drupalGet('node/' . $this->test_node->nid);
-    $this->assertText('1 read', t('Node is read once.'));
+    $this->assertText('1 view', t('Node is viewed once.'));
 
     $this->drupalGet('admin/reports/pages');
     $this->assertText('node/' . $this->test_node->nid, t('Hit URL found.'));
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 4d225d5b35709a83ac6c696d6b8e04a193814826..907b7b5f18a5704e9d91ecbedce1cf12d409129b 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -2746,10 +2746,10 @@ function hook_schema_alter(&$schema) {
  *
  * @see hook_query_TAG_alter()
  * @see node_query_node_access_alter()
- * @see QueryAlterableInterface
- * @see SelectQueryInterface
+ * @see AlterableInterface
+ * @see SelectInterface
  */
-function hook_query_alter(QueryAlterableInterface $query) {
+function hook_query_alter(Drupal\Database\Query\AlterableInterface $query) {
   if ($query->hasTag('micro_limit')) {
     $query->range(0, 2);
   }
@@ -2763,10 +2763,10 @@ function hook_query_alter(QueryAlterableInterface $query) {
  *
  * @see hook_query_alter()
  * @see node_query_node_access_alter()
- * @see QueryAlterableInterface
- * @see SelectQueryInterface
+ * @see AlterableInterface
+ * @see SelectInterface
  */
-function hook_query_TAG_alter(QueryAlterableInterface $query) {
+function hook_query_TAG_alter(Drupal\Database\Query\AlterableInterface $query) {
   // Skip the extra expensive alterations if site has no node access control modules.
   if (!node_access_view_all_nodes()) {
     // Prevent duplicates records.
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 45e369f0aaac3796fe6a0d9700f9e3c68f145059..03116583761edc6ef55674c6b36da1e591fe3a8d 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * @file
  * Install, update and uninstall functions for the system module.
@@ -180,7 +182,7 @@ function system_requirements($phase) {
   }
   else {
     // Database information.
-    $class = 'DatabaseTasks_' . Database::getConnection()->driver();
+    $class = Database::getConnection()->getDriverClass('Install\\Tasks');
     $tasks = new $class();
     $requirements['database_system'] = array(
       'title' => $t('Database system'),
@@ -461,7 +463,7 @@ function system_requirements($phase) {
       $requirements['update status'] = array(
         'value' => $t('Not enabled'),
         'severity' => REQUIREMENT_WARNING,
-        'description' => $t('Update notifications are not enabled. It is <strong>highly recommended</strong> that you enable the update manager module from the <a href="@module">module administration page</a> in order to stay up-to-date on new releases. For more information, <a href="@update">Update status handbook page</a>.', array('@update' => 'http://drupal.org/handbook/modules/update', '@module' => url('admin/modules'))),
+        'description' => $t('Update notifications are not enabled. It is <strong>highly recommended</strong> that you enable the Update Manager module from the <a href="@module">module administration page</a> in order to stay up-to-date on new releases. For more information, <a href="@update">Update status handbook page</a>.', array('@update' => 'http://drupal.org/handbook/modules/update', '@module' => url('admin/modules'))),
       );
     }
     else {
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 449cf7e10404224eb043fb95c80ba48cb762d7f5..684714908bccabbc64dfda6c536ff1301da67ae9 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -115,7 +115,7 @@ function system_help($path, $arg) {
         }
       }
       else {
-        $output .= '<p>' . t('Regularly review available updates to maintain a secure and current site. Always run the <a href="@update-php">update script</a> each time a module is updated. Enable the Update manager module to update and install modules and themes.', array('@update-php' => $base_url . '/core/update.php')) . '</p>';
+        $output .= '<p>' . t('Regularly review available updates to maintain a secure and current site. Always run the <a href="@update-php">update script</a> each time a module is updated. Enable the Update Manager module to update and install modules and themes.', array('@update-php' => $base_url . '/core/update.php')) . '</p>';
       }
       return $output;
     case 'admin/modules/uninstall':
diff --git a/core/modules/system/system.test b/core/modules/system/system.test
index d246fc9bc59c0280df4378b58b9ed30bffeb75b4..64774c458146e553b481ff7db1381f81dcf2d1ce 100644
--- a/core/modules/system/system.test
+++ b/core/modules/system/system.test
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Database;
+
 /**
  * @file
  * Tests for system.module.
@@ -480,7 +482,7 @@ class ModuleDependencyTestCase extends ModuleTestCase {
     $edit['modules[Core][forum][enable]'] = 'forum';
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
     $this->assertModules(array('forum'), FALSE);
-    $this->assertText(t('You must enable the Poll, PHP filter modules to install Forum.'), t('Dependency chain created.'));
+    $this->assertText(t('You must enable the Poll, PHP Filter modules to install Forum.'), t('Dependency chain created.'));
     $edit['modules[Core][poll][enable]'] = 'poll';
     $edit['modules[Core][php][enable]'] = 'php';
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
diff --git a/core/modules/system/system.theme.css b/core/modules/system/system.theme.css
index c3913c16759e939bf6b6dbabc6f199d2cf5aa80d..d5f41e1743444c6b5a5af9e9d4f6bba9010573bc 100644
--- a/core/modules/system/system.theme.css
+++ b/core/modules/system/system.theme.css
@@ -37,6 +37,16 @@ tr.odd {
   padding: 0.1em 0.6em;
 }
 
+/**
+ * Publishing status.
+ */
+.unpublished {
+  background-color: #fff4f4;
+}
+.preview {
+  background-color: #ffffea;
+}
+
 /**
  * Markup generated by theme_tablesort_indicator().
  */
diff --git a/core/modules/taxonomy/taxonomy.css b/core/modules/taxonomy/taxonomy.css
index 36cd641bec2e46a36491b88467d3b43097374282..433b3d65b21e68385fe69e7815f0bcd2fe5f4240 100644
--- a/core/modules/taxonomy/taxonomy.css
+++ b/core/modules/taxonomy/taxonomy.css
@@ -1,12 +1,12 @@
 
 tr.taxonomy-term-preview {
-  background-color: #EEE;
+  background-color: #eee;
 }
 tr.taxonomy-term-divider-top {
   border-bottom: none;
 }
 tr.taxonomy-term-divider-bottom {
-  border-top: 1px dotted #CCC;
+  border-top: 1px dotted #ccc;
 }
 .taxonomy-term-description {
   margin: 5px 0 20px;
diff --git a/core/modules/taxonomy/taxonomy.pages.inc b/core/modules/taxonomy/taxonomy.pages.inc
index e1b47a964de14c35067bb4deb1ee12374c3433c9..4bdcbc5141f38bea75d5ef9c6fc04b7cf08deaf4 100644
--- a/core/modules/taxonomy/taxonomy.pages.inc
+++ b/core/modules/taxonomy/taxonomy.pages.inc
@@ -79,8 +79,6 @@ function taxonomy_term_feed($term) {
 /**
  * Page callback: Outputs JSON for taxonomy autocomplete suggestions.
  *
- * Path: taxonomy/autocomplete
- *
  * This callback outputs term name suggestions in response to Ajax requests
  * made by the taxonomy autocomplete widget for taxonomy term reference
  * fields. The output is a JSON object of plain-text term suggestions, keyed by
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index 254a41915546c40bce18484a6e0e19bf0af79c0d..4b1b8938bc90789ba10b5df498283e5e2be1a424 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -67,8 +67,6 @@ function toolbar_menu() {
 /**
  * Page callback: Toggles the visibility of the toolbar drawer.
  *
- * Path: toolbar/toggle
- *
  * @see toolbar_menu().
  */
 function toolbar_toggle_page() {
diff --git a/core/modules/translation/translation.info b/core/modules/translation/translation.info
index ab6feece51249f7d00019b37d3c0b62f1807be0a..7d574abeb4981fd0c055ff0dfe06236a4533ddaf 100644
--- a/core/modules/translation/translation.info
+++ b/core/modules/translation/translation.info
@@ -1,4 +1,4 @@
-name = Content translation
+name = Content Translation
 description = Allows content to be translated into different languages.
 dependencies[] = locale
 package = Core
diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module
index e1de320be8b7e28d504e26ea568107debe219ab2..bb2d7e3a301808720e3d2419e0fc2048786ed36c 100644
--- a/core/modules/translation/translation.module
+++ b/core/modules/translation/translation.module
@@ -32,7 +32,7 @@ function translation_help($path, $arg) {
     case 'admin/help#translation':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('The Content translation module allows content to be translated into different languages. Working with the <a href="@locale">Locale module</a> (which manages enabled languages and provides translation for the site interface), the Content translation module is key to creating and maintaining translated site content. For more information, see the online handbook entry for <a href="@translation">Content translation module</a>.', array('@locale' => url('admin/help/locale'), '@translation' => 'http://drupal.org/handbook/modules/translation/')) . '</p>';
+      $output .= '<p>' . t('The Content Translation module allows content to be translated into different languages. Working with the <a href="@locale">Locale module</a> (which manages enabled languages and provides translation for the site interface), the Content Translation module is key to creating and maintaining translated site content. For more information, see the online handbook entry for <a href="@translation">Content Translation module</a>.', array('@locale' => url('admin/help/locale'), '@translation' => 'http://drupal.org/handbook/modules/translation/')) . '</p>';
       $output .= '<h3>' . t('Uses') . '</h3>';
       $output .= '<dl>';
       $output .= '<dt>' . t('Configuring content types for translation') . '</dt>';
diff --git a/core/modules/update/update.css b/core/modules/update/update.css
index d30dfb6e50b824acc6dca856fc8506922bb54380..80d0bdbb0f6407b25f299ee06459e7b5b9c70f8d 100644
--- a/core/modules/update/update.css
+++ b/core/modules/update/update.css
@@ -100,7 +100,7 @@ table.update,
 }
 
 .update table.version-security .version-title {
-  color: #970F00;
+  color: #970f00;
 }
 
 .update table.version-recommended-strong .version-title {
@@ -109,7 +109,7 @@ table.update,
 
 .update .security-error {
   font-weight: bold;
-  color: #970F00;
+  color: #970f00;
 }
 
 .update .check-manually {
diff --git a/core/modules/update/update.info b/core/modules/update/update.info
index 83b9857d0e1031ad4cd461ff41e9068991bb8c81..cdad3003e7b0b0768bb560704e9abbc3ba9872dd 100644
--- a/core/modules/update/update.info
+++ b/core/modules/update/update.info
@@ -1,4 +1,4 @@
-name = Update manager
+name = Update Manager
 description = Checks for available updates, and can securely install or update modules and themes via a web interface.
 version = VERSION
 package = Core
diff --git a/core/modules/update/update.module b/core/modules/update/update.module
index 6577af74cd38c57751ec8573d60b5bb9de18c119..020f026a29a64fcdd1369d2e8b8b15b3b9816338 100644
--- a/core/modules/update/update.module
+++ b/core/modules/update/update.module
@@ -81,7 +81,7 @@ function update_help($path, $arg) {
     case 'admin/help#update':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t("The Update manager module periodically checks for new versions of your site's software (including contributed modules and themes), and alerts administrators to available updates. In order to provide update information, anonymous usage statistics are sent to Drupal.org. If desired, you may disable the Update manager module from the <a href='@modules'>Module administration page</a>. For more information, see the online handbook entry for <a href='@update'>Update manager module</a>.", array('@update' => 'http://drupal.org/handbook/modules/update', '@modules' => url('admin/modules'))) . '</p>';
+      $output .= '<p>' . t("The Update Manager module periodically checks for new versions of your site's software (including contributed modules and themes), and alerts administrators to available updates. In order to provide update information, anonymous usage statistics are sent to Drupal.org. If desired, you may disable the Update Manager module from the <a href='@modules'>Module administration page</a>. For more information, see the online handbook entry for <a href='@update'>Update Manager module</a>.", array('@update' => 'http://drupal.org/handbook/modules/update', '@modules' => url('admin/modules'))) . '</p>';
       // Only explain the Update manager if it has not been disabled.
       if (update_manager_access()) {
         $output .= '<p>' . t('The Update manager also allows administrators to update and install modules and themes through the administration interface.') . '</p>';
@@ -89,11 +89,11 @@ function update_help($path, $arg) {
       $output .= '<h3>' . t('Uses') . '</h3>';
       $output .= '<dl>';
       $output .= '<dt>' . t('Checking for available updates') . '</dt>';
-      $output .= '<dd>' . t('A report of <a href="@update-report">available updates</a> will alert you when new releases are available for download. You may configure options for the frequency for checking updates (which are performed during <a href="@cron">cron</a> runs) and e-mail notifications at the <a href="@update-settings">Update manager settings</a>  page.', array('@update-report' => url('admin/reports/updates'), '@cron' => 'http://drupal.org/cron', '@update-settings' => url('admin/reports/updates/settings'))) . '</dd>';
+      $output .= '<dd>' . t('A report of <a href="@update-report">available updates</a> will alert you when new releases are available for download. You may configure options for the frequency for checking updates (which are performed during <a href="@cron">cron</a> runs) and e-mail notifications at the <a href="@update-settings">Update Manager settings</a>  page.', array('@update-report' => url('admin/reports/updates'), '@cron' => 'http://drupal.org/cron', '@update-settings' => url('admin/reports/updates/settings'))) . '</dd>';
       // Only explain the Update manager if it has not been disabled.
       if (update_manager_access()) {
         $output .= '<dt>' . t('Performing updates through the user interface') . '</dt>';
-        $output .= '<dd>' . t('The Update manager module allows administrators to perform updates directly through the administration interface. At the top of the <a href="@modules_page">modules</a> and <a href="@themes_page">themes</a> pages you will see a link to update to new releases. This will direct you to the <a href="@update-page">update page</a> where you see a listing of all the missing updates and confirm which ones you want to upgrade. From there, you are prompted for your FTP/SSH password, which then transfers the files into your Drupal installation, overwriting your old files. More detailed instructions can be found in the <a href="@update">online handbook</a>.', array('@modules_page' => url('admin/modules'), '@themes_page' => url('admin/appearance'),  '@update-page' => url('admin/reports/updates/update'), '@update' => 'http://drupal.org/handbook/modules/update')) . '</dd>';
+        $output .= '<dd>' . t('The Update Manager module allows administrators to perform updates directly through the administration interface. At the top of the <a href="@modules_page">modules</a> and <a href="@themes_page">themes</a> pages you will see a link to update to new releases. This will direct you to the <a href="@update-page">update page</a> where you see a listing of all the missing updates and confirm which ones you want to upgrade. From there, you are prompted for your FTP/SSH password, which then transfers the files into your Drupal installation, overwriting your old files. More detailed instructions can be found in the <a href="@update">online handbook</a>.', array('@modules_page' => url('admin/modules'), '@themes_page' => url('admin/appearance'),  '@update-page' => url('admin/reports/updates/update'), '@update' => 'http://drupal.org/handbook/modules/update')) . '</dd>';
         $output .= '<dt>' . t('Installing new modules and themes through the user interface') . '</dt>';
         $output .= '<dd>' . t('You can also install new modules and themes in the same fashion, through the <a href="@install">install page</a>, or by clicking the <em>Install new module/theme</em> link at the top of the <a href="@modules_page">modules</a> and <a href="@themes_page">themes</a> pages. In this case, you are prompted to provide either the URL to the download, or to upload a packaged release file from your local computer.', array('@modules_page' => url('admin/modules'), '@themes_page' => url('admin/appearance'), '@install' => url('admin/reports/updates/install'))) . '</dd>';
       }
diff --git a/core/modules/user/user.css b/core/modules/user/user.css
index a3033073345ef0f680dace4b2036ef7def3a2a51..bbfeb833c65638ee6d44ebc47029fad13087bddb 100644
--- a/core/modules/user/user.css
+++ b/core/modules/user/user.css
@@ -42,14 +42,14 @@
   font-weight: bold;
 }
 .password-indicator {
-  background-color: #C4C4C4;
+  background-color: #c4c4c4;
   height: 0.3em;
   width: 100%;
 }
 .password-indicator div {
   height: 100%;
   width: 0%;
-  background-color: #47C965;
+  background-color: #47c965;
 }
 input.password-confirm,
 input.password-field {
@@ -66,7 +66,7 @@ div.form-item div.password-suggestions {
   padding: 0.2em 0.5em;
   margin: 0.7em 0;
   width: 38.5em;
-  border: 1px solid #B4B4B4;
+  border: 1px solid #b4b4b4;
 }
 div.password-suggestions ul {
   margin-bottom: 0;
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index f4479ec4c2c9f5a4bbca5241939a3283a5db20c8..3ac4cd682313d0f4a76bdaf4ab163dddeb4ded60 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Database\Query\SelectInterface;
+
 /**
  * @file
  * Enables the user registration and login system.
@@ -3377,7 +3379,7 @@ function user_filters() {
  * @param $query
  *   Query object that should be filtered.
  */
-function user_build_filter_query(SelectQuery $query) {
+function user_build_filter_query(SelectInterface $query) {
   $filters = user_filters();
   // Extend Query with filter conditions.
   foreach (isset($_SESSION['user_overview_filter']) ? $_SESSION['user_overview_filter'] : array() as $filter) {
diff --git a/core/themes/bartik/css/colors.css b/core/themes/bartik/css/colors.css
index fd83374a54b67df5cf7dcafd94610d51916d2a5c..f2a324996fa48fc276d87f577a83e64cde71f81f 100644
--- a/core/themes/bartik/css/colors.css
+++ b/core/themes/bartik/css/colors.css
@@ -31,7 +31,7 @@ body.overlay {
   background-image: linear-gradient(top, #0779bf 0%, #48a9e4 100%);
 }
 a {
-  color: #0071B3;
+  color: #0071b3;
 }
 a:hover,
 a:focus {
diff --git a/core/themes/bartik/css/style.css b/core/themes/bartik/css/style.css
index 850a69c2df2f4c876332bd520e9c63c8669ec73d..3413e178a14652f53b30008a9c28e4a720e0444d 100644
--- a/core/themes/bartik/css/style.css
+++ b/core/themes/bartik/css/style.css
@@ -187,7 +187,7 @@ table tr th {
 table tr th,
 table tr th a,
 table tr th a:hover {
-  color: #FFF;
+  color: #fff;
   font-weight: bold;
 }
 table tbody tr th {
@@ -570,33 +570,28 @@ h1#page-title {
 .node .content {
   font-size: 1.071em;
 }
-.node-teaser .content {
+.view-mode-teaser .content {
   font-size: 1em;
 }
-.node-teaser h2 {
+.view-mode-teaser h2 {
   margin-top: 0;
   padding-top: 0.5em;
 }
-.node-teaser h2 a {
+.view-mode-teaser h2 a {
   color: #181818;
 }
-.node-teaser {
+.view-mode-teaser {
   border-bottom: 1px solid #d3d7d9;
   margin-bottom: 30px;
   padding-bottom: 15px;
 }
-.node-sticky {
+.view-mode-teaser.sticky {
   background: #f9f9f9;
   background: rgba(0, 0, 0, 0.024);
   border: 1px solid #d3d7d9;
   padding: 0 15px 15px;
 }
-.node-full {
-  background: none;
-  border: none;
-  padding: 0;
-}
-.node-teaser .content {
+.view-mode-teaser .content {
   clear: none;
   line-height: 1.6;
 }
@@ -622,8 +617,8 @@ h1#page-title {
 .field-type-taxonomy-term-reference ul.links {
   font-size: 0.8em;
 }
-.node-teaser .field-type-taxonomy-term-reference .field-label,
-.node-teaser .field-type-taxonomy-term-reference ul.links {
+.view-mode-teaser .field-type-taxonomy-term-reference .field-label,
+.view-mode-teaser .field-type-taxonomy-term-reference ul.links {
   font-size: 0.821em;
 }
 .field-type-taxonomy-term-reference ul.links {
@@ -647,11 +642,11 @@ ul.links {
   color: #68696b;
   font-size: 0.821em;
 }
-.node-unpublished {
+.unpublished {
   margin: -20px -15px 0;
   padding: 20px 15px 0;
 }
-.node-unpublished .comment-text .comment-arrow {
+.unpublished .comment-text .comment-arrow {
   border-left: 1px solid #fff4f4;
   border-right: 1px solid #fff4f4;
 }
@@ -1597,10 +1592,10 @@ div.admin-panel .description {
 
 /* ---------- book ----------- */
 .book-navigation .menu {
-  border-top: 1px solid #D6D6D6;
+  border-top: 1px solid #d6d6d6;
 }
 .book-navigation .book-pager {
-  border-bottom: 1px solid #D6D6D6;
-  border-top: 1px solid #D6D6D6;
+  border-bottom: 1px solid #d6d6d6;
+  border-top: 1px solid #d6d6d6;
   margin: 0;
 }
diff --git a/core/themes/bartik/template.php b/core/themes/bartik/template.php
index 59a909984bcc78e173572762f1d2b6fe57cb73f1..459a593eaf96d3027131d1fb9e742bdc5f0d2311 100644
--- a/core/themes/bartik/template.php
+++ b/core/themes/bartik/template.php
@@ -101,15 +101,6 @@ function bartik_process_maintenance_page(&$variables) {
   }
 }
 
-/**
- * Override or insert variables into the node template.
- */
-function bartik_preprocess_node(&$variables) {
-  if ($variables['view_mode'] == 'full' && node_is_page($variables['node'])) {
-    $variables['classes_array'][] = 'node-full';
-  }
-}
-
 /**
  * Override or insert variables into the block template.
  */
diff --git a/core/themes/bartik/templates/node.tpl.php b/core/themes/bartik/templates/node.tpl.php
index 234b8994ab5ea85c2785108a989211100b468953..eb745a41a72d377dbd0d343492a8c4d5e00d572f 100644
--- a/core/themes/bartik/templates/node.tpl.php
+++ b/core/themes/bartik/templates/node.tpl.php
@@ -26,13 +26,13 @@
  *   - node-[type]: The current node type. For example, if the node is a
  *     "Article" it would result in "node-article". Note that the machine
  *     name will often be in a short form of the human readable label.
- *   - node-teaser: Nodes in teaser form.
- *   - node-preview: Nodes in preview mode.
+ *   - view-mode-[view_mode]: The View Mode of the node e.g. teaser or full.
+ *   - preview: Nodes in preview mode.
  *   The following are controlled through the node publishing options.
- *   - node-promoted: Nodes promoted to the front page.
- *   - node-sticky: Nodes ordered above other non-sticky nodes in teaser
+ *   - promoted: Nodes promoted to the front page.
+ *   - sticky: Nodes ordered above other non-sticky nodes in teaser
  *     listings.
- *   - node-unpublished: Unpublished nodes visible only to administrators.
+ *   - unpublished: Unpublished nodes visible only to administrators.
  * - $title_prefix (array): An array containing additional output populated by
  *   modules, intended to be displayed in front of the main title tag that
  *   appears in the template.
diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css
index 301659c4b13efa5256fb435c631eaa56ad4d4f30..66914f6fb1036a278006b51eb373ad136c4eabe9 100644
--- a/core/themes/seven/style.css
+++ b/core/themes/seven/style.css
@@ -8,7 +8,7 @@ body {
   font: normal 81.3%/1.538em "Lucida Grande", "Lucida Sans Unicode", sans-serif;
 }
 a {
-  color: #0074BD;
+  color: #0074bd;
   text-decoration: none;
 }
 a:hover {
@@ -939,13 +939,13 @@ div.add-or-remove-shortcuts {
   padding: 1px 8px;
 }
 #field-display-overview tr.field-formatter-settings-changed {
-  background: #FFFFBB;
+  background: #ffffbb;
 }
 #field-display-overview tr.drag {
-  background: #FFEE77;
+  background: #ffee77;
 }
 #field-display-overview tr.field-formatter-settings-editing {
-  background: #D5E9F2;
+  background: #d5e9f2;
 }
 #field-display-overview .field-formatter-settings-edit-form .form-item {
   margin: 10px 0;
diff --git a/profiles/minimal/minimal.install b/profiles/minimal/minimal.install
index d5b85c5f23dd5fd1ed4b4345e9c85c5be76922d2..e02ffccfa9ae86d74af72d1a1db665730ed9a736 100644
--- a/profiles/minimal/minimal.install
+++ b/profiles/minimal/minimal.install
@@ -1,9 +1,15 @@
 <?php
+/**
+ * @file
+ * Install, update and uninstall functions for the the minimal install profile.
+ */
 
 /**
  * Implements hook_install().
  *
- * Perform actions to set up the site for this profile.
+ * Performs actions to set up the site for this profile.
+ *
+ * @see system_install()
  */
 function minimal_install() {
   // Enable Bartik theme and set it as default theme instead of Stark.
diff --git a/profiles/minimal/minimal.profile b/profiles/minimal/minimal.profile
index ff8f28105ec1f661e7d248f1c36ad7357af25079..fe6da8c3287c5cd7428d0d33665170ad5a2a1eac 100644
--- a/profiles/minimal/minimal.profile
+++ b/profiles/minimal/minimal.profile
@@ -1,7 +1,11 @@
 <?php
+/**
+ * @file
+ * Enables modules and site configuration for a minimal site installation.
+ */
 
 /**
- * Implements hook_form_FORM_ID_alter().
+ * Implements hook_form_FORM_ID_alter() for install_configure_form().
  *
  * Allows the profile to alter the site configuration form.
  */
diff --git a/profiles/standard/standard.install b/profiles/standard/standard.install
index e570c184c4da3bc34b5d1ee3a59aff4f19e5a6da..1c8636d7454ed2606f613724f254235f6ba9b65c 100644
--- a/profiles/standard/standard.install
+++ b/profiles/standard/standard.install
@@ -1,9 +1,15 @@
 <?php
+/**
+ * @file
+ * Install, update and uninstall functions for the standard install profile.
+ */
 
 /**
  * Implements hook_install().
  *
  * Perform actions to set up the site for this profile.
+ *
+ * @see system_install()
  */
 function standard_install() {
   // Add text formats.
diff --git a/profiles/standard/standard.profile b/profiles/standard/standard.profile
index 7671c12a2d992cdd8753847214ededbeaaa4663d..d554c937939991f98583ddf0f96f2bb013b049bb 100644
--- a/profiles/standard/standard.profile
+++ b/profiles/standard/standard.profile
@@ -1,7 +1,11 @@
 <?php
+/**
+ * @file
+ * Enables modules and site configuration for a standard site installation.
+ */
 
 /**
- * Implements hook_form_FORM_ID_alter().
+ * Implements hook_form_FORM_ID_alter() for install_configure_form().
  *
  * Allows the profile to alter the site configuration form.
  */
diff --git a/profiles/testing/testing.install b/profiles/testing/testing.install
index 19092d424020deedd4c90c3168c6f382390b753d..afd6d1ca48d7d93484c89a23af728aec850d6f22 100644
--- a/profiles/testing/testing.install
+++ b/profiles/testing/testing.install
@@ -1,9 +1,15 @@
 <?php
+/**
+ * @file
+ * Install, update and uninstall functions for the testing profile.
+ */
 
 /**
  * Implements hook_install().
  *
  * Perform actions to set up the site for this profile.
+ *
+ * @see system_install()
  */
 function testing_install() {
   // Allow visitor account creation, but with administrative approval.
diff --git a/profiles/testing/testing.profile b/profiles/testing/testing.profile
index a4abe2dafcb3fabac023b6d4630c24fed41379c0..3df8aa22f51a1d7ab546e25ccfc2e953290850e9 100644
--- a/profiles/testing/testing.profile
+++ b/profiles/testing/testing.profile
@@ -1,2 +1,5 @@
 <?php
-
+/**
+ * @file
+ * Installation profile for tests.
+ */
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index b24ff5dbb5b7e6f6f29d2cc4c3ac1001e1d37b16..230a7659c9dbb3a66825159da4a09b4ae03a43f8 100755
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -522,7 +522,7 @@
 /**
  * Authorized file system operations:
  *
- * The Update manager module included with Drupal provides a mechanism for
+ * The Update Manager module included with Drupal provides a mechanism for
  * site administrators to securely install missing updates for the site
  * directly through the web user interface by providing either SSH or FTP
  * credentials. This allows the site to update the new files as the user who