diff --git a/composer.json b/composer.json
index 8d5cd3a..396b43f 100644
--- a/composer.json
+++ b/composer.json
@@ -4,8 +4,44 @@
   "type": "project",
   "license": "GPL-2.0+",
   "require": {
+<<<<<<< HEAD
     "composer/installers": "^1.0.21",
     "drupal/core": "~8.0"
+=======
+    "php": ">=5.4.5",
+    "sdboyer/gliph": "0.1.*",
+    "symfony/class-loader": "2.5.*",
+    "symfony/css-selector": "2.5.*",
+    "symfony/dependency-injection": "2.5.*",
+    "symfony/event-dispatcher": "2.5.*",
+    "symfony/http-foundation": "2.5.*",
+    "symfony/http-kernel": "2.5.*",
+    "symfony/routing": "2.5.*",
+    "symfony/serializer": "2.5.*",
+    "symfony/validator": "2.5.*",
+    "symfony/yaml": "dev-master#499f7d7aa96747ad97940089bd7a1fb24ad8182a",
+    "twig/twig": "1.16.*",
+    "doctrine/common": "dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5",
+    "doctrine/annotations": "1.2.*",
+    "guzzlehttp/guzzle": "~5.0",
+    "symfony-cmf/routing": "1.3.*",
+    "easyrdf/easyrdf": "0.8.*",
+    "phpunit/phpunit": "4.1.*",
+    "phpunit/phpunit-mock-objects": "dev-master#e60bb929c50ae4237aaf680a4f6773f4ee17f0a2",
+    "zendframework/zend-feed": "2.2.*",
+    "mikey179/vfsStream": "1.*",
+    "stack/builder": "1.0.*",
+    "egulias/email-validator": "1.2.*"
+  },
+  "autoload": {
+    "psr-4": {
+      "Drupal\\Core\\": "core/lib/Drupal/Core",
+      "Drupal\\Component\\": "core/lib/Drupal/Component"
+    },
+    "files": [
+      "core/lib/Drupal.php"
+    ]
+>>>>>>> Applying patch from issue 2209307 comment 34
   },
   "minimum-stability": "dev",
   "prefer-stable": true,
diff --git a/core/drivers/fake/fake.info.yml b/core/drivers/fake/fake.info.yml
new file mode 100644
index 0000000..0c4fbd6
--- /dev/null
+++ b/core/drivers/fake/fake.info.yml
@@ -0,0 +1,5 @@
+# @todo Rename this driver from 'fake' to e.g. 'test_db_driver'.
+#   (\Drupal\fake\* lacks context.)
+type: driver
+core: 8.x
+name: Fake database driver for use in unit tests
diff --git a/core/drivers/fake/src/ConditionResolver.php b/core/drivers/fake/src/ConditionResolver.php
new file mode 100644
index 0000000..016d42d
--- /dev/null
+++ b/core/drivers/fake/src/ConditionResolver.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\ConditionResolver.
+ */
+
+
+namespace Drupal\fake;
+
+use Drupal\Core\Database\Query\Condition;
+
+class ConditionResolver {
+
+  /**
+   * Match a row against a group of conditions.
+   *
+   * @param \Drupal\fake\DatabaseRowInterface $row
+   *   The database row object.
+   * @param \Drupal\Core\Database\Query\Condition $condition_group
+   *   The condition group object.
+   *
+   * @return bool
+   *   TRUE if there is a match.
+   */
+  public static function matchGroup(DatabaseRowInterface $row, Condition $condition_group) {
+    $conditions = $condition_group->conditions();
+    $and = $conditions['#conjunction'] == 'AND';
+    unset($conditions['#conjunction']);
+    $match = TRUE;
+    foreach ($conditions as $condition) {
+      $match = $condition['field'] instanceof Condition ? static::matchGroup($row, $condition['field']) : static::matchSingle($row, $condition);
+      // For AND, finish matching on the first fail. For OR, finish on first
+      // success.
+      if ($and != $match) {
+        break;
+      }
+    }
+    return $match;
+  }
+
+  /**
+   * Match a single row and its condition.
+   *
+   * @param \Drupal\migrate\tests\DatabaseRowInterface $row
+   *   The row to match.
+   *
+   * @param array $condition
+   *   An array representing a single condition.
+   *
+   * @return bool
+   *   TRUE if the condition matches.
+   *
+   * @throws \Exception
+   */
+  protected static function matchSingle(DatabaseRowInterface $row, array $condition) {
+    $row_value = $row->getValue($condition['field']);
+    switch ($condition['operator']) {
+      case '=':
+        return $row_value == $condition['value'];
+
+      case '<=':
+        return $row_value <= $condition['value'];
+
+      case '>=':
+        return $row_value >= $condition['value'];
+
+      case '!=':
+        return $row_value != $condition['value'];
+
+      case '<>':
+        return $row_value != $condition['value'];
+
+      case '<':
+        return $row_value < $condition['value'];
+
+      case '>':
+        return $row_value > $condition['value'];
+
+      case 'IN':
+        return in_array($row_value, $condition['value']);
+
+      case 'IS NULL':
+        return !isset($row_value);
+
+      case 'IS NOT NULL':
+        return isset($row_value);
+
+      default:
+        throw new \Exception(sprintf('operator %s is not supported', $condition['operator']));
+    }
+  }
+
+}
diff --git a/core/drivers/fake/src/DatabaseRow.php b/core/drivers/fake/src/DatabaseRow.php
new file mode 100644
index 0000000..0bf7bfc
--- /dev/null
+++ b/core/drivers/fake/src/DatabaseRow.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\DatabaseRow.
+ */
+
+namespace Drupal\fake;
+
+class DatabaseRow implements DatabaseRowInterface {
+
+  /**
+   * Construct a new row.
+   *
+   * @param array $row
+   *   The row data.
+   */
+  public function __construct(array $row) {
+    $this->row = $row;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValue($field) {
+    return $this->row[$field];
+  }
+
+}
diff --git a/core/drivers/fake/src/DatabaseRowInterface.php b/core/drivers/fake/src/DatabaseRowInterface.php
new file mode 100644
index 0000000..444a578
--- /dev/null
+++ b/core/drivers/fake/src/DatabaseRowInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\DatabaseRowInterface.
+ */
+
+namespace Drupal\fake;
+
+interface DatabaseRowInterface {
+
+  /**
+   * Get the field value from the row.
+   *
+   * @param mixed $field
+   *   The field to get the value of.
+   *
+   * @return mixed
+   *   The field value from the row.
+   */
+  public function getValue($field);
+}
diff --git a/core/drivers/fake/src/DatabaseRowSelect.php b/core/drivers/fake/src/DatabaseRowSelect.php
new file mode 100644
index 0000000..c7479c6
--- /dev/null
+++ b/core/drivers/fake/src/DatabaseRowSelect.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\DatabaseRowSelect.
+ */
+
+namespace Drupal\fake;
+
+class DatabaseRowSelect extends DatabaseRow {
+
+  /**
+   * Construct a new database row.
+   *
+   * @param array $row
+   *   The row data.
+   * @param array $fields_with_table
+   *   The fields with a table.
+   * @param array $fields
+   *   The fields.
+   */
+  public function __construct(array $row, array $fields_with_table, array $fields) {
+    $this->fieldsWithTable = $fields_with_table;
+    $this->fields = $fields;
+    parent::__construct($row);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValue($field) {
+    $field_info = isset($this->fieldsWithTable[$field]) ? $this->fieldsWithTable[$field] : $this->fields[$field];
+    if (array_key_exists($field_info['field'], $this->row[$field_info['table']]['result'])) {
+      $index = 'result';
+    }
+    else {
+      $index = 'all';
+    }
+    return $this->row[$field_info['table']][$index][$field_info['field']];
+  }
+
+}
diff --git a/core/drivers/fake/src/FakeConnection.php b/core/drivers/fake/src/FakeConnection.php
new file mode 100644
index 0000000..0c4c639
--- /dev/null
+++ b/core/drivers/fake/src/FakeConnection.php
@@ -0,0 +1,168 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\FakeConnection.
+ */
+
+namespace Drupal\fake;
+
+use Drupal\Core\Database\Connection;
+
+/**
+ * Defines a fake connection for use during testing.
+ */
+class FakeConnection extends Connection {
+
+  /**
+   * Table prefix on the database.
+   *
+   * @var string
+   */
+  protected $tablePrefix;
+
+  /**
+   * Connection options for the database.
+   *
+   * @var array
+   */
+  protected $connectionOptions;
+
+  /**
+   * Constructs a FakeConnection.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param array $connection_options
+   *   (optional) The array of connection options for the database.
+   * @param string $prefix
+   *   (optional) The table prefix on the database.
+   */
+  public function __construct(array $database_contents, $connection_options = array(), $prefix = '') {
+    $this->databaseContents = $database_contents;
+    $this->connectionOptions = $connection_options;
+    $this->tablePrefix = $prefix;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConnectionOptions() {
+    return $this->connectionOptions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function tablePrefix($table = 'default') {
+    return $this->tablePrefix;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function select($table, $alias = NULL, array $options = array()) {
+    return new FakeSelect($this->databaseContents, $table, $alias);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function insert($table, array $options = array()) {
+    return new FakeInsert($this->databaseContents, $table);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function merge($table, array $options = array()) {
+    return new FakeMerge($this->databaseContents, $table);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function update($table, array $options = array()) {
+    return new FakeUpdate($this->databaseContents, $table);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function truncate($table, array $options = array()) {
+    return new FakeTruncate($this->databaseContents, $table);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function schema() {
+    return new Schema($this->databaseContents);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query($query, array $args = array(), $options = array()) {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function queryTemporary($query, array $args = array(), array $options = array()) {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function driver() {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function databaseType() {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function destroy() {
+    $this->schema = NULL;
+    $this->databaseContents = NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createDatabase($database) {
+    // There is nothing to do.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function mapConditionOperator($operator) {
+    throw new \Exception('Method not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function nextId($existing_id = 0) {
+    throw new \Exception('Method not supported');
+  }
+
+}
diff --git a/core/drivers/fake/src/FakeInsert.php b/core/drivers/fake/src/FakeInsert.php
new file mode 100644
index 0000000..9756983
--- /dev/null
+++ b/core/drivers/fake/src/FakeInsert.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\FakeInsert.
+ */
+
+namespace Drupal\fake;
+
+use Drupal\Core\Database\Query\Insert;
+use Drupal\Core\Database\Query\SelectInterface;
+
+/**
+ * Defines FakeInsert for use in database tests.
+ */
+class FakeInsert extends Insert {
+
+  /**
+   * The database contents.
+   *
+   * @var array
+   */
+  protected $databaseContents;
+
+  /**
+   * The database table to insert into.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * Constructs a fake insert object.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param string $table
+   *   The table to insert into.
+   * @param array $options
+   *   (optional) The database options. Not used.
+   */
+  public function __construct(array &$database_contents, $table, array $options = array()) {
+    $this->databaseContents = &$database_contents;
+    $this->table = $table;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function useDefaults(array $fields) {
+    throw new \Exception('This method is not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function from(SelectInterface $query) {
+    throw new \Exception('This method is not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    foreach ($this->insertValues as $values) {
+      $this->databaseContents[$this->table][] = array_combine($this->insertFields, $values);
+    }
+  }
+
+}
diff --git a/core/drivers/fake/src/FakeMerge.php b/core/drivers/fake/src/FakeMerge.php
new file mode 100644
index 0000000..550243c
--- /dev/null
+++ b/core/drivers/fake/src/FakeMerge.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\FakeMerge.
+ */
+
+namespace Drupal\fake;
+
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\Query\InvalidMergeQueryException;
+use Drupal\Core\Database\Query\Merge;
+
+/**
+ * Defines FakeMerge for use in database tests.
+ */
+class FakeMerge extends Merge {
+
+  /**
+   * Constructs a fake merge object and initializes the conditions.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param string $table
+   *   The database table to merge into.
+   */
+  public function __construct(array &$database_contents, $table) {
+    $this->databaseContents = &$database_contents;
+    $this->table = $table;
+    $this->conditionTable = $table;
+    $this->condition = new Condition('AND');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    if (!count($this->condition)) {
+      throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
+    }
+    $select = new FakeSelect($this->databaseContents, $this->conditionTable, 'c');
+    $count = $select
+      ->condition($this->condition)
+      ->countQuery()
+      ->execute()
+      ->fetchField();
+    if ($count) {
+      $update = new FakeUpdate($this->databaseContents, $this->table);
+      $update
+        ->fields($this->updateFields)
+        ->condition($this->condition)
+        ->execute();
+      return self::STATUS_UPDATE;
+    }
+    $insert = new FakeInsert($this->databaseContents, $this->table);
+    $insert->fields($this->insertFields)->execute();
+    return self::STATUS_INSERT;
+  }
+
+}
diff --git a/core/drivers/fake/src/FakeSelect.php b/core/drivers/fake/src/FakeSelect.php
new file mode 100644
index 0000000..c6bd19b
--- /dev/null
+++ b/core/drivers/fake/src/FakeSelect.php
@@ -0,0 +1,540 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\FakeSelect.
+ */
+
+namespace Drupal\fake;
+
+use Drupal\Component\Utility\String;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\Query\PlaceholderInterface;
+use Drupal\Core\Database\Query\Select;
+use Drupal\Core\Database\Query\SelectInterface;
+
+class FakeSelect extends Select {
+
+  /**
+   * Contents of the pseudo-database.
+   *
+   * Keys are table names and values are arrays of rows in the table.
+   * Every row there contains all table field values keyed by field name.
+   *
+   * @code
+   * array(
+   *   'user' => array(
+   *     array(
+   *       'uid' => 1,
+   *       'name' => 'admin',
+   *     ),
+   *     array(
+   *       'uid' => 2,
+   *       'name' => 'alice',
+   *     ),
+   *   ),
+   *   'node' => array(
+   *     array(
+   *       'nid' => 1,
+   *     )
+   *   )
+   * )
+   * @endcode
+   *
+   * @var array
+   */
+  protected $databaseContents;
+
+  protected $countQuery = FALSE;
+  protected $fieldsWithTable = array();
+
+  /**
+   * Constructs a new FakeSelect.
+   *
+   * @param array $database_contents
+   *   An array of mocked database content.
+   * @param string $table
+   *   The base table name used within fake select.
+   * @param string $alias
+   *   The base table alias used within fake select.
+   * @param string $conjunction
+   *   The operator to use to combine conditions: 'AND' or 'OR'.
+   */
+  public function __construct(array $database_contents, $table, $alias, $conjunction = 'AND') {
+    $this->databaseContents = $database_contents;
+    $this->addJoin(NULL, $table, $alias);
+    $this->where = new Condition($conjunction);
+    $this->having = new Condition($conjunction);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    return $this->addJoin('LEFT', $table, $alias, $condition, $arguments);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    if ($table instanceof SelectInterface) {
+      // @todo implement this.
+      throw new \Exception('Subqueries are not supported at this moment.');
+    }
+    $alias = parent::addJoin($type, $table, $alias, $condition, $arguments);
+    if (isset($type)) {
+      if ($type != 'INNER' && $type != 'LEFT') {
+        throw new \Exception(sprintf('%s type not supported, only INNER and LEFT.', $type));
+      }
+      if (!preg_match('/^(\w+\.)?(\w+)\s*=\s*(\w+)\.(\w+)$/', $condition, $matches)) {
+        throw new \Exception('Only x.field1 = y.field2 conditions are supported.' . $condition);
+      }
+      if (!$matches[1] && count($this->tables) == 2) {
+        $aliases = array_keys($this->tables);
+        $matches[1] = $aliases[0];
+      }
+      else {
+        $matches[1] = substr($matches[1], 0, -1);
+      }
+      if (!$matches[1]) {
+        throw new \Exception('Only x.field1 = y.field2 conditions are supported.' . $condition);
+      }
+      if ($matches[1] == $alias) {
+        $this->tables[$alias] += array(
+          'added_field' => $matches[2],
+          'original_table_alias' => $matches[3],
+          'original_field' => $matches[4],
+        );
+      }
+      elseif ($matches[3] == $alias) {
+        $this->tables[$alias] += array(
+          'added_field' => $matches[4],
+          'original_table_alias' => $matches[1],
+          'original_field' => $matches[2],
+        );
+      }
+      else {
+        throw new \Exception('The JOIN condition does not contain the alias of the joined table.');
+      }
+    }
+    return $alias;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    // @todo: Implement distinct() handling.
+
+    // Single table count queries often do not contain fields which this class
+    // does not support otherwise, so add a shortcut.
+    if (count($this->tables) == 1 && $this->countQuery) {
+      $table_info = reset($this->tables);
+      $where = $this->where;
+      if (!empty($this->databaseContents[$table_info['table']])) {
+        $results = array_filter($this->databaseContents[$table_info['table']], function ($row_array) use ($where) {
+          return ConditionResolver::matchGroup(new DatabaseRow($row_array), $where);
+        });
+      }
+      else {
+        $results = array();
+      }
+    }
+    else {
+      $all_rows = $this->executeJoins();
+      $all_rows = $this->resolveConditions($this->where, $all_rows);
+      if (!empty($this->order)) {
+        usort($all_rows, array($this, 'sortCallback'));
+      }
+      // Now flatten the rows so that each row becomes a field alias => value
+      // array.
+      $results = array();
+      foreach ($all_rows as $table_rows) {
+        $result_row = array();
+        foreach ($table_rows as $row) {
+          $result_row += $row['result'];
+        }
+        $results[] = $result_row;
+      }
+    }
+    if (!empty($this->range)) {
+      $results = array_slice($results, $this->range['start'], $this->range['length']);
+    }
+    if ($this->countQuery) {
+      $results = array(array(count($results)));
+    }
+    return new FakeStatement($results);
+  }
+
+  /**
+   * Create an initial result set by executing the joins and picking fields.
+   *
+   * @return array
+   *   A multidimensional array, the first key are table aliases, the second
+   *   are field aliases, the values are the database contents or NULL in case
+   *   of JOINs.
+   */
+  protected function executeJoins() {
+    $fields = array();
+    foreach ($this->fields as $field_info) {
+      $this->fieldsWithTable[$field_info['table'] . '.' . $field_info['field']] = $field_info;
+      $fields[$field_info['table']][$field_info['field']] = NULL;
+    }
+    foreach ($this->tables as $alias => $table_info) {
+      if ($table = reset($this->databaseContents[$table_info['table']])) {
+        foreach (array_keys($table) as $field) {
+          if (!isset($this->fields[$field])) {
+            $this->fieldsWithTable[$field] = array(
+              'table' => $alias,
+              'field' => $field,
+            );
+            $this->fieldsWithTable["$alias.$field"] = array(
+              'table' => $alias,
+              'field' => $field,
+            );
+          }
+        }
+      }
+    }
+    // This will contain a multiple dimensional array. The first key will be a
+    // table alias, the second either result or all, the third will be a field
+    // alias. all contains every field in the table with the original field
+    // names while result contains only the fields requested. This allows for
+    // filtering on fields that were not added via addField().
+    $results = array();
+    foreach ($this->tables as $table_alias => $table_info) {
+      // The base table for this query.
+      if (empty($table_info['join type'])) {
+        foreach ($this->databaseContents[$table_info['table']] as $candidate_row) {
+          $results[] = $this->getNewRow($table_alias, $fields, $candidate_row);
+        }
+      }
+      else {
+        $new_rows = array();
+
+        // Dynamically build a set of joined rows. Check existing rows and see
+        // if they can be joined with incoming rows.
+        foreach ($results as $row) {
+          $joined = FALSE;
+          foreach ($this->databaseContents[$table_info['table']] as $candidate_row) {
+            if ($row[$table_info['original_table_alias']]['result'][$table_info['original_field']] == $candidate_row[$table_info['added_field']]) {
+              $joined = TRUE;
+              $new_rows[] = $this->getNewRow($table_alias, $fields, $candidate_row, $row);
+            }
+          }
+          if (!$joined && $table_info['join type'] == 'LEFT') {
+            // Because PHP doesn't scope their foreach statements,
+            // $candidate_row may contain the last value assigned to it from the
+            // previous statement.
+            // @TODO: empty tables? Those are a problem.
+            $keys = array_keys($candidate_row);
+            $values = array_fill(0, count($keys), NULL);
+            $new_row = array(
+              'result' => $fields[$table_alias],
+              'all' => array_combine($keys, $values),
+            );
+            $new_rows[] = array($table_alias => $new_row) + $row;
+          }
+        }
+        $results = $new_rows;
+      }
+    }
+    return $results;
+  }
+
+  /**
+   * Retrieves a new row.
+   *
+   * @param string $table_alias
+   * @param array $fields
+   * @param array $candidate_row
+   * @param array $row
+   *
+   * @return array
+   */
+  protected function getNewRow($table_alias, $fields, $candidate_row, $row = array()) {
+    $new_row[$table_alias]['all'] = $candidate_row;
+    foreach ($fields[$table_alias] as $field => $v) {
+      $new_row[$table_alias]['result'][$field] = $candidate_row[$field];
+    }
+    return $new_row + $row;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function countQuery() {
+    $query = clone $this;
+    return $query->setCountQuery();
+  }
+
+  /**
+   * Set this query to be a count query.
+   */
+  protected function setCountQuery() {
+    $this->countQuery = TRUE;
+    return $this;
+  }
+
+  /**
+   * usort callback to order the results.
+   */
+  protected function sortCallback($a, $b) {
+    $a_row = new DatabaseRowSelect($a, $this->fieldsWithTable, $this->fields);
+    $b_row = new DatabaseRowSelect($b, $this->fieldsWithTable, $this->fields);
+    foreach ($this->order as $field => $direction) {
+      $a_value = $a_row->getValue($field);
+      $b_value = $b_row->getValue($field);
+      if ($a_value != $b_value) {
+        return (($a_value < $b_value) == ($direction == 'ASC')) ? -1 : 1;
+      }
+    }
+    return 0;
+  }
+
+  /**
+   * Resolves conditions by removing non-matching rows.
+   *
+   * @param \Drupal\Core\Database\Query\Condition $condition_group
+   *   The condition group to check.
+   * @param array $rows
+   *   An array of rows excluding non-matching rows.
+   *
+   * @return \Drupal\fake\ConditionResolver
+   *   The condition resolver object.
+   */
+  protected function resolveConditions(Condition $condition_group, array &$rows) {
+    $fields_with_table = $this->fieldsWithTable;
+    $fields = $this->fields;
+    return array_filter($rows, function ($row_array) use ($condition_group, $fields_with_table, $fields) {
+      $row = new DatabaseRowSelect($row_array, $fields_with_table, $fields);
+      return ConditionResolver::matchGroup($row, $condition_group);
+    });
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderBy($field, $direction = 'ASC') {
+    $this->order[$field] = strtoupper($direction);
+    return $this;
+  }
+
+  // ================== we could support these.
+  /**
+   * {@inheritdoc}
+   */
+  public function groupBy($field) {
+    // @todo: Implement groupBy() method.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function havingCondition($field, $value = NULL, $operator = NULL) {
+    // @todo: Implement havingCondition() method.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function uniqueIdentifier() {
+    // TODO: Implement uniqueIdentifier() method.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  // ================== the rest won't be supported, ever.
+  /**
+   * {@inheritdoc}
+   */
+  public function nextPlaceholder() {
+    // TODO: Implement nextPlaceholder() method.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isPrepared() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preExecute(SelectInterface $query = NULL) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function where($snippet, $args = array()) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function extend($extender_name) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getExpressions() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getGroupBy() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getUnion() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function forUpdate($set = TRUE) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &conditions() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderRandom() {
+    // We could implement this but why bother.
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function union(SelectInterface $query, $type = '') {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addExpression($expression, $alias = NULL, $arguments = array()) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getTables() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getArguments(PlaceholderInterface $query_place_holder = NULL) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getOrderBy() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function &getFields() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function exists(SelectInterface $select) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function notExists(SelectInterface $select) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function arguments() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function compile(Connection $connection, PlaceholderInterface $query_place_holder) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function compiled() {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Fake select test',
+      'description' => 'Tests for fake select plugin.',
+      'group' => 'Migrate',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields($table_alias, array $fields = array()) {
+    if (!$fields) {
+      $table = $this->tables[$table_alias]['table'];
+      if (!empty($this->databaseContents[$table])) {
+        $fields = array_keys(reset($this->databaseContents[$table]));
+      }
+      else {
+        throw new \Exception(String::format('All fields on empty table @table is not supported.', array('@table' => $table)));
+      }
+    }
+    return parent::fields($table_alias, $fields);
+  }
+}
diff --git a/core/drivers/fake/src/FakeStatement.php b/core/drivers/fake/src/FakeStatement.php
new file mode 100644
index 0000000..a8aafea
--- /dev/null
+++ b/core/drivers/fake/src/FakeStatement.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\FakeStatement.
+ */
+
+namespace Drupal\fake;
+
+use Drupal\Core\Database\RowCountException;
+use Drupal\Core\Database\StatementInterface;
+
+/**
+ * Represents a fake prepared statement.
+ */
+class FakeStatement extends \ArrayIterator implements StatementInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute($args = array(), $options = array()) {
+    throw new \Exception('This method is not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQueryString() {
+    throw new \Exception('This method is not supported');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function rowCount() {
+    throw new RowCountException();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchField($index = 0) {
+    $row = array_values($this->current());
+    $return = $row[$index];
+    $this->next();
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchAssoc() {
+    $return = FALSE;
+    if ($this->valid()) {
+      $return = $this->current();
+      $this->next();
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchCol($index = 0) {
+    $return = array();
+    foreach ($this as $row) {
+      $row = array_values($row);
+      $return[] = $row[$index];
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchAllKeyed($key_index = 0, $value_index = 1) {
+    $return = array();
+    foreach ($this as $row) {
+      $row = array_values($row);
+      $return[$row[$key_index]] = $row[$value_index];
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchAllAssoc($key, $fetch = NULL) {
+    $return = array();
+    foreach ($this as $row) {
+      $return[$row[$key]] = $row;
+    }
+    return $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchObject() {
+    $return = $this->fetchAssoc();
+    return $return === FALSE ? FALSE : (object) $return;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Fake statement test',
+      'description' => 'Tests for fake statement plugin.',
+      'group' => 'Migrate',
+    );
+  }
+
+}
diff --git a/core/drivers/fake/src/FakeTruncate.php b/core/drivers/fake/src/FakeTruncate.php
new file mode 100644
index 0000000..358e638
--- /dev/null
+++ b/core/drivers/fake/src/FakeTruncate.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\FakeTruncate.
+ */
+
+namespace Drupal\fake;
+
+/**
+ * Defines FakeTruncate for use in database tests.
+ */
+class FakeTruncate {
+
+  /**
+   * Constructs a FakeTruncate object.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param string $table
+   *   The table to truncate.
+   */
+  public function __construct(array &$database_contents, $table) {
+    $this->databaseContents = &$database_contents;
+    $this->table = $table;
+  }
+
+  /**
+   * Executes the TRUNCATE query.
+   */
+  public function execute() {
+    $this->databaseContents[$this->table] = array();
+  }
+
+}
diff --git a/core/drivers/fake/src/FakeUpdate.php b/core/drivers/fake/src/FakeUpdate.php
new file mode 100644
index 0000000..c817309
--- /dev/null
+++ b/core/drivers/fake/src/FakeUpdate.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\FakeUpdate.
+ */
+
+namespace Drupal\fake;
+
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\Query\SelectInterface;
+use Drupal\Core\Database\Query\Update;
+
+/**
+ * Defines FakeUpdate for use in database tests.
+ */
+class FakeUpdate extends Update {
+
+  /**
+   * The database table to update.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * The database contents.
+   *
+   * @var array
+   */
+  protected $databaseContents;
+
+  /**
+   * Constructs a FakeUpdate object and initializes the condition.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   * @param string $table
+   *   The table to update.
+   */
+  public function __construct(array &$database_contents, $table) {
+    $this->databaseContents = &$database_contents;
+    $this->table = $table;
+    $this->condition = new Condition('AND');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    $affected = 0;
+    if (isset($this->databaseContents[$this->table])) {
+      $fields = $this->fields;
+      $condition = $this->condition;
+      array_walk($this->databaseContents[$this->table], function (&$row_array) use ($fields, $condition, &$affected) {
+        $row = new DatabaseRow($row_array);
+        if (ConditionResolver::matchGroup($row, $condition)) {
+          $row_array = $fields + $row_array;
+          $affected++;
+        }
+      });
+    }
+    return $affected;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function exists(SelectInterface $select) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function where($snippet, $args = array()) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function expression($field, $expression, array $arguments = NULL) {
+    throw new \Exception(sprintf('Method "%s" is not supported', __METHOD__));
+  }
+
+}
diff --git a/core/drivers/fake/src/Install/Tasks.php b/core/drivers/fake/src/Install/Tasks.php
new file mode 100644
index 0000000..79c5532
--- /dev/null
+++ b/core/drivers/fake/src/Install/Tasks.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\Install\Tasks
+ */
+
+namespace Drupal\fake\Install;
+
+use Drupal\Core\Database\Install\Tasks as InstallTasks;
+
+/**
+ * Usually used to specify installation tasks but here we're only interested
+ * in setting $error to TRUE.
+ */
+class Tasks extends InstallTasks {
+  /**
+   * Prevent the installer from recognising this as a potential database driver.
+   * @TODO Looks like this is needed only if we define $pdoDriver to something valid e.g. mysql.
+   * Not sure we need to do that. We may not need this file at all?
+   *
+   * @var boolean
+   */
+  protected $error = TRUE;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function name() {
+    return t('Fake database connection for use in unit tests');
+  }
+}
diff --git a/core/drivers/fake/src/Schema.php b/core/drivers/fake/src/Schema.php
new file mode 100644
index 0000000..80c322b
--- /dev/null
+++ b/core/drivers/fake/src/Schema.php
@@ -0,0 +1,248 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fake\Schema.
+ */
+
+namespace Drupal\fake;
+
+use Drupal\Core\Database\Schema as BaseSchema;
+
+class Schema extends BaseSchema {
+
+  /**
+   * As set on MigrateSqlSourceTestCase::databaseContents.
+   *
+   * @var array
+   */
+  public $databaseContents;
+
+  /**
+   * Constructs a fake database schema.
+   *
+   * @param array $database_contents
+   *   The database contents faked as an array. Each key is a table name, each
+   *   value is a list of table rows.
+   */
+  public function __construct(array &$database_contents) {
+    $this->uniqueIdentifier = uniqid('', TRUE);
+
+    // @todo Maybe we can generate an internal representation.
+    $this->databaseContents = &$database_contents;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function tableExists($table) {
+    return in_array($table, array_keys($this->databaseContents));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prefixNonTable($table) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getPrefixInfo($table = 'default', $add_prefix = TRUE) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addField($table, $field, $spec, $keys_new = array()) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addIndex($table, $name, $fields) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addPrimaryKey($table, $fields) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addUniqueKey($table, $name, $fields) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * PHP magic __clone() method.
+   */
+  public function __clone() {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function copyTable($source, $destination) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createTable($name, $table) {
+    #throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropField($table, $field) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropIndex($table, $name) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropPrimaryKey($table) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropTable($table) {
+    unset($this->databaseContents[$table]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function dropUniqueKey($table, $name) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fieldExists($table, $column) {
+    if (!empty($this->databaseContents[$table])) {
+      $row = reset($this->databaseContents[$table]);
+      return isset($row[$column]);
+    }
+    else {
+      throw new \Exception("Can't determine whether field exists with an empty / nonexistent table.");
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fieldNames($fields) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fieldSetDefault($table, $field, $default) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fieldSetNoDefault($table, $field) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function findTables($table_expression) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldTypeMap() {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function indexExists($table, $name) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function nextPlaceholder() {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareComment($comment, $length = NULL) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function renameTable($table, $new_name) {
+    throw new \Exception(sprintf('Unsupported method "%s"', __METHOD__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function uniqueIdentifier() {
+    return $this->uniqueIdentifier;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Fake database schema',
+      'description' => 'Tests for fake database schema plugin.',
+      'group' => 'Migrate',
+    );
+  }
+
+}
diff --git a/core/drivers/mysql/mysql.info.yml b/core/drivers/mysql/mysql.info.yml
new file mode 100644
index 0000000..b6939d9
--- /dev/null
+++ b/core/drivers/mysql/mysql.info.yml
@@ -0,0 +1,3 @@
+type: driver
+core: 8.x
+name: MySQL, MariaDB, Percona Server, or equivalent
diff --git a/core/drivers/mysql/src/Connection.php b/core/drivers/mysql/src/Connection.php
new file mode 100644
index 0000000..4cda20a
--- /dev/null
+++ b/core/drivers/mysql/src/Connection.php
@@ -0,0 +1,332 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Connection.
+=======
+ * Contains Drupal\mysql\Connection
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Connection.php
+ */
+
+namespace Drupal\mysql;
+
+use Drupal\Core\Database\DatabaseExceptionWrapper;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\DatabaseNotFoundException;
+use Drupal\Core\Database\TransactionCommitFailedException;
+use Drupal\Core\Database\DatabaseException;
+use Drupal\Core\Database\Connection as DatabaseConnection;
+use Drupal\Component\Utility\Unicode;
+
+/**
+ * @addtogroup database
+ * @{
+ */
+
+class Connection extends DatabaseConnection {
+
+  /**
+   * Error code for "Unknown database" error.
+   */
+  const DATABASE_NOT_FOUND = 1049;
+
+  /**
+   * Error code for "Can't initialize character set" error.
+   */
+  const UNSUPPORTED_CHARSET = 2019;
+
+  /**
+   * Flag to indicate if the cleanup function in __destruct() should run.
+   *
+   * @var bool
+   */
+  protected $needsCleanup = FALSE;
+
+  /**
+   * The minimal possible value for the max_allowed_packet setting of MySQL.
+   *
+   * @link https://mariadb.com/kb/en/mariadb/server-system-variables/#max_allowed_packet
+   * @link https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_allowed_packet
+   *
+   * @var int
+   */
+  const MIN_MAX_ALLOWED_PACKET = 1024;
+
+  /**
+   * Constructs a Connection object.
+   */
+  public function __construct(\PDO $connection, array $connection_options = array()) {
+    parent::__construct($connection, $connection_options);
+
+    // This driver defaults to transaction support, except if explicitly passed FALSE.
+    $this->transactionSupport = !isset($connection_options['transactions']) || ($connection_options['transactions'] !== FALSE);
+
+    // MySQL never supports transactional DDL.
+    $this->transactionalDDLSupport = FALSE;
+
+    $this->connectionOptions = $connection_options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query($query, array $args = array(), $options = array()) {
+    try {
+      return parent::query($query, $args, $options);
+    } catch (DatabaseException $e) {
+      if ($e->getPrevious()->errorInfo[1] == 1153) {
+        // If a max_allowed_packet error occurs the message length is truncated.
+        // This should prevent the error from recurring if the exception is
+        // logged to the database using dblog or the like.
+        $message = Unicode::truncateBytes($e->getMessage(), self::MIN_MAX_ALLOWED_PACKET);
+        $e = new DatabaseExceptionWrapper($message, $e->getCode(), $e->getPrevious());
+      }
+      throw $e;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function open(array &$connection_options = array()) {
+    if (isset($connection_options['_dsn_utf8_fallback']) && $connection_options['_dsn_utf8_fallback'] === TRUE) {
+      // Only used during the installer version check, as a fallback from utf8mb4.
+      $charset = 'utf8';
+    }
+    else {
+      $charset = 'utf8mb4';
+    }
+    // The DSN should use either a socket or a host/port.
+    if (isset($connection_options['unix_socket'])) {
+      $dsn = 'mysql:unix_socket=' . $connection_options['unix_socket'];
+    }
+    else {
+      // Default to TCP connection on port 3306.
+      $dsn = 'mysql:host=' . $connection_options['host'] . ';port=' . (empty($connection_options['port']) ? 3306 : $connection_options['port']);
+    }
+    // Character set is added to dsn to ensure PDO uses the proper character
+    // set when escaping. This has security implications. See
+    // https://www.drupal.org/node/1201452 for further discussion.
+    $dsn .= ';charset=' . $charset;
+    if (!empty($connection_options['database'])) {
+      $dsn .= ';dbname=' . $connection_options['database'];
+    }
+    // Allow PDO options to be overridden.
+    $connection_options += array(
+      'pdo' => array(),
+    );
+    $connection_options['pdo'] += array(
+      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
+      // So we don't have to mess around with cursors and unbuffered queries by default.
+      \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
+      // Make sure MySQL returns all matched rows on update queries including
+      // rows that actually didn't have to be updated because the values didn't
+      // change. This matches common behavior among other database systems.
+      \PDO::MYSQL_ATTR_FOUND_ROWS => TRUE,
+      // Because MySQL's prepared statements skip the query cache, because it's dumb.
+      \PDO::ATTR_EMULATE_PREPARES => TRUE,
+    );
+    if (defined('\PDO::MYSQL_ATTR_MULTI_STATEMENTS')) {
+      // An added connection option in PHP 5.5.21 to optionally limit SQL to a
+      // single statement like mysqli.
+      $connection_options['pdo'] += [\PDO::MYSQL_ATTR_MULTI_STATEMENTS => FALSE];
+    }
+
+    $pdo = new \PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
+
+    // Force MySQL to use the UTF-8 character set. Also set the collation, if a
+    // certain one has been set; otherwise, MySQL defaults to
+    // 'utf8mb4_general_ci' for utf8mb4.
+    if (!empty($connection_options['collation'])) {
+      $pdo->exec('SET NAMES ' . $charset . ' COLLATE ' . $connection_options['collation']);
+    }
+    else {
+      $pdo->exec('SET NAMES ' . $charset);
+    }
+
+    // Set MySQL init_commands if not already defined.  Default Drupal's MySQL
+    // behavior to conform more closely to SQL standards.  This allows Drupal
+    // to run almost seamlessly on many different kinds of database systems.
+    // These settings force MySQL to behave the same as postgresql, or sqlite
+    // in regards to syntax interpretation and invalid data handling.  See
+    // https://www.drupal.org/node/344575 for further discussion. Also, as MySQL
+    // 5.5 changed the meaning of TRADITIONAL we need to spell out the modes one
+    // by one.
+    $connection_options += array(
+      'init_commands' => array(),
+    );
+    $connection_options['init_commands'] += array(
+      'sql_mode' => "SET sql_mode = 'ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,ONLY_FULL_GROUP_BY'",
+    );
+    // Execute initial commands.
+    foreach ($connection_options['init_commands'] as $sql) {
+      $pdo->exec($sql);
+    }
+
+    return $pdo;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function serialize() {
+    // Cleanup the connection, much like __destruct() does it as well.
+    if ($this->needsCleanup) {
+      $this->nextIdDelete();
+    }
+    $this->needsCleanup = FALSE;
+
+    return parent::serialize();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __destruct() {
+    if ($this->needsCleanup) {
+      $this->nextIdDelete();
+    }
+  }
+
+  public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
+    return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options);
+  }
+
+  public function queryTemporary($query, array $args = array(), array $options = array()) {
+    $tablename = $this->generateTemporaryTableName();
+    $this->query('CREATE TEMPORARY TABLE {' . $tablename . '} Engine=MEMORY ' . $query, $args, $options);
+    return $tablename;
+  }
+
+  public function driver() {
+    return 'mysql';
+  }
+
+  public function databaseType() {
+    return 'mysql';
+  }
+
+  /**
+   * Overrides \Drupal\Core\Database\Connection::createDatabase().
+   *
+   * @param string $database
+   *   The name of the database to create.
+   *
+   * @throws \Drupal\Core\Database\DatabaseNotFoundException
+   */
+  public function createDatabase($database) {
+    // Escape the database name.
+    $database = Database::getConnection()->escapeDatabase($database);
+
+    try {
+      // Create the database and set it as active.
+      $this->connection->exec("CREATE DATABASE $database");
+      $this->connection->exec("USE $database");
+    }
+    catch (\Exception $e) {
+      throw new DatabaseNotFoundException($e->getMessage());
+    }
+  }
+
+  public function mapConditionOperator($operator) {
+    // We don't want to override any of the defaults.
+    return NULL;
+  }
+
+  public function nextId($existing_id = 0) {
+    $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID));
+    // This should only happen after an import or similar event.
+    if ($existing_id >= $new_id) {
+      // If we INSERT a value manually into the sequences table, on the next
+      // INSERT, MySQL will generate a larger value. However, there is no way
+      // of knowing whether this value already exists in the table. MySQL
+      // provides an INSERT IGNORE which would work, but that can mask problems
+      // other than duplicate keys. Instead, we use INSERT ... ON DUPLICATE KEY
+      // UPDATE in such a way that the UPDATE does not do anything. This way,
+      // duplicate keys do not generate errors but everything else does.
+      $this->query('INSERT INTO {sequences} (value) VALUES (:value) ON DUPLICATE KEY UPDATE value = value', array(':value' => $existing_id));
+      $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID));
+    }
+    $this->needsCleanup = TRUE;
+    return $new_id;
+  }
+
+  public function nextIdDelete() {
+    // While we want to clean up the table to keep it up from occupying too
+    // much storage and memory, we must keep the highest value in the table
+    // because InnoDB uses an in-memory auto-increment counter as long as the
+    // server runs. When the server is stopped and restarted, InnoDB
+    // reinitializes the counter for each table for the first INSERT to the
+    // table based solely on values from the table so deleting all values would
+    // be a problem in this case. Also, TRUNCATE resets the auto increment
+    // counter.
+    try {
+      $max_id = $this->query('SELECT MAX(value) FROM {sequences}')->fetchField();
+      // We know we are using MySQL here, no need for the slower db_delete().
+      $this->query('DELETE FROM {sequences} WHERE value < :value', array(':value' => $max_id));
+    }
+    // During testing, this function is called from shutdown with the
+    // simpletest prefix stored in $this->connection, and those tables are gone
+    // by the time shutdown is called so we need to ignore the database
+    // errors. There is no problem with completely ignoring errors here: if
+    // these queries fail, the sequence will work just fine, just use a bit
+    // more database storage and memory.
+    catch (DatabaseException $e) {
+    }
+  }
+
+  /**
+   * Overridden to work around issues to MySQL not supporting transactional DDL.
+   */
+  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 (!$this->connection->commit()) {
+          throw new TransactionCommitFailedException();
+        }
+      }
+      else {
+        // Attempt to release this savepoint in the standard way.
+        try {
+          $this->query('RELEASE SAVEPOINT ' . $name);
+        }
+        catch (DatabaseExceptionWrapper $e) {
+          // However, in MySQL (InnoDB), savepoints are automatically committed
+          // when tables are altered or created (DDL transactions are not
+          // supported). This can cause exceptions due to trying to release
+          // savepoints which no longer exist.
+          //
+          // To avoid exceptions when no actual error has occurred, we silently
+          // succeed for MySQL error code 1305 ("SAVEPOINT does not exist").
+          if ($e->getPrevious()->errorInfo[1] == '1305') {
+            // If one SAVEPOINT was released automatically, then all were.
+            // Therefore, clean the transaction stack.
+            $this->transactionLayers = array();
+            // We also have to explain to PDO that the transaction stack has
+            // been cleaned-up.
+            $this->connection->commit();
+          }
+          else {
+            throw $e;
+          }
+        }
+      }
+    }
+  }
+
+}
+
+
+/**
+ * @} End of "addtogroup database".
+ */
diff --git a/core/drivers/mysql/src/Delete.php b/core/drivers/mysql/src/Delete.php
new file mode 100644
index 0000000..8428b55
--- /dev/null
+++ b/core/drivers/mysql/src/Delete.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Delete.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Delete.
+=======
+ * Contains Drupal\mysql\Delete
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Delete.php
+ */
+
+namespace Drupal\mysql;
+
+use Drupal\Core\Database\Query\Delete as QueryDelete;
+
+class Delete extends QueryDelete { }
diff --git a/core/drivers/mysql/src/Insert.php b/core/drivers/mysql/src/Insert.php
new file mode 100644
index 0000000..3b40999
--- /dev/null
+++ b/core/drivers/mysql/src/Insert.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Insert.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Insert.
+=======
+ * Contains Drupal\mysql\Insert
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Insert.php
+ */
+
+namespace Drupal\mysql;
+
+use Drupal\Core\Database\Query\Insert as QueryInsert;
+
+class Insert extends QueryInsert {
+
+  public function execute() {
+    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)) {
+      $max_placeholder = 0;
+      $values = array();
+      foreach ($this->insertValues as $insert_values) {
+        foreach ($insert_values as $value) {
+          $values[':db_insert_placeholder_' . $max_placeholder++] = $value;
+        }
+      }
+    }
+    else {
+      $values = $this->fromQuery->getArguments();
+    }
+
+    $last_insert_id = $this->connection->query((string) $this, $values, $this->queryOptions);
+
+    // Re-initialize the values array so that we can re-use this query.
+    $this->insertValues = array();
+
+    return $last_insert_id;
+  }
+
+  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 we're selecting from a SelectQuery, finish building the query and
+    // pass it back, as any remaining options are irrelevant.
+    if (!empty($this->fromQuery)) {
+      $insert_fields_string = $insert_fields ? ' (' . implode(', ', $insert_fields) . ') ' : ' ';
+      return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery;
+    }
+
+    $query = $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
+
+    $values = $this->getInsertPlaceholderFragment($this->insertValues, $this->defaultFields);
+    $query .= implode(', ', $values);
+
+    return $query;
+  }
+}
diff --git a/core/drivers/mysql/src/Install/Tasks.php b/core/drivers/mysql/src/Install/Tasks.php
new file mode 100644
index 0000000..e5f6812
--- /dev/null
+++ b/core/drivers/mysql/src/Install/Tasks.php
@@ -0,0 +1,182 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Install\Tasks.
+=======
+ * Contains Drupal\mysql\Install\Tasks
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Install/Tasks.php
+ */
+
+namespace Drupal\mysql\Install;
+
+use Drupal\Core\Database\Install\Tasks as InstallTasks;
+use Drupal\Core\Database\Database;
+use Drupal\mysql\Connection;
+use Drupal\Core\Database\DatabaseNotFoundException;
+
+/**
+ * Specifies installation tasks for MySQL and equivalent databases.
+ */
+class Tasks extends InstallTasks {
+
+  /**
+   * Minimum required MySQLnd version.
+   */
+  const MYSQLND_MINIMUM_VERSION = '5.0.9';
+
+  /**
+   * Minimum required libmysqlclient version.
+   */
+  const LIBMYSQLCLIENT_MINIMUM_VERSION = '5.5.3';
+
+  /**
+   * The PDO driver name for MySQL and equivalent databases.
+   *
+   * @var string
+   */
+  protected $pdoDriver = 'mysql';
+
+  /**
+   * Constructs a \Drupal\Core\Database\Driver\mysql\Install\Tasks object.
+   */
+  public function __construct() {
+    $this->tasks[] = array(
+      'arguments' => array(),
+      'function' => 'ensureInnoDbAvailable',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function name() {
+    return t('MySQL, MariaDB, Percona Server, or equivalent');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function minimumVersion() {
+    return '5.5.3';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function connect() {
+    try {
+      // This doesn't actually test the connection.
+      db_set_active();
+      // Now actually do a check.
+      try {
+        Database::getConnection();
+      }
+      catch (\Exception $e) {
+        // Detect utf8mb4 incompability.
+        if ($e->getCode() == Connection::UNSUPPORTED_CHARSET) {
+          $this->fail(t('Your MySQL server and PHP MySQL driver must support utf8mb4 character encoding. Make sure to use a database system that supports this (such as MySQL/MariaDB/Percona 5.5.3 and up), and that the utf8mb4 character set is compiled in. See the <a href="@documentation" target="_blank">MySQL documentation</a> for more information.', array('@documentation' => 'https://dev.mysql.com/doc/refman/5.0/en/cannot-initialize-character-set.html')));
+          $info = Database::getConnectionInfo();
+          $info_copy = $info;
+          // Set a flag to fall back to utf8. Note: this flag should only be
+          // used here and is for internal use only.
+          $info_copy['default']['_dsn_utf8_fallback'] = TRUE;
+          // In order to change the Database::$databaseInfo array, we need to
+          // remove the active connection, then re-add it with the new info.
+          Database::removeConnection('default');
+          Database::addConnectionInfo('default', 'default', $info_copy['default']);
+          // Connect with the new database info, using the utf8 character set so
+          // that we can run the checkEngineVersion test.
+          Database::getConnection();
+          // Revert to the old settings.
+          Database::removeConnection('default');
+          Database::addConnectionInfo('default', 'default', $info['default']);
+        }
+        else {
+          // Rethrow the exception.
+          throw $e;
+        }
+      }
+      $this->pass('Drupal can CONNECT to the database ok.');
+    }
+    catch (\Exception $e) {
+      // Attempt to create the database if it is not found.
+      if ($e->getCode() == Connection::DATABASE_NOT_FOUND) {
+        // Remove the database string from connection info.
+        $connection_info = Database::getConnectionInfo();
+        $database = $connection_info['default']['database'];
+        unset($connection_info['default']['database']);
+
+        // In order to change the Database::$databaseInfo array, need to remove
+        // the active connection, then re-add it with the new info.
+        Database::removeConnection('default');
+        Database::addConnectionInfo('default', 'default', $connection_info['default']);
+
+        try {
+          // Now, attempt the connection again; if it's successful, attempt to
+          // create the database.
+          Database::getConnection()->createDatabase($database);
+        }
+        catch (DatabaseNotFoundException $e) {
+          // Still no dice; probably a permission issue. Raise the error to the
+          // installer.
+          $this->fail(t('Database %database not found. The server reports the following message when attempting to create the database: %error.', array('%database' => $database, '%error' => $e->getMessage())));
+        }
+      }
+      else {
+        // Database connection failed for some other reason than the database
+        // not existing.
+        $this->fail(t('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 or does the database user have sufficient privileges to create the database?</li><li>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;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormOptions(array $database) {
+    $form = parent::getFormOptions($database);
+    if (empty($form['advanced_options']['port']['#default_value'])) {
+      $form['advanced_options']['port']['#default_value'] = '3306';
+    }
+
+    return $form;
+  }
+
+  /**
+   * Ensure that InnoDB is available.
+   */
+  function ensureInnoDbAvailable() {
+    $engines = Database::getConnection()->query('SHOW ENGINES')->fetchAllKeyed();
+    if (isset($engines['MyISAM']) && $engines['MyISAM'] == 'DEFAULT' && !isset($engines['InnoDB'])) {
+      $this->fail(t('The MyISAM storage engine is not supported.'));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function checkEngineVersion() {
+    parent::checkEngineVersion();
+
+    // Ensure that the MySQL driver supports utf8mb4 encoding.
+    $version = Database::getConnection()->clientVersion();
+    if (FALSE !== strpos($version, 'mysqlnd')) {
+      // The mysqlnd driver supports utf8mb4 starting at version 5.0.9.
+      $version = preg_replace('/^\D+([\d.]+).*/', '$1', $version);
+      if (version_compare($version, self::MYSQLND_MINIMUM_VERSION, '<')) {
+        $this->fail(t("The MySQLnd driver version %version is less than the minimum required version. Upgrade to MySQLnd version %mysqlnd_minimum_version or up, or alternatively switch mysql drivers to libmysqlclient version %libmysqlclient_minimum_version or up.", array('%version' => $version, '%mysqlnd_minimum_version' => self::MYSQLND_MINIMUM_VERSION, '%libmysqlclient_minimum_version' => self::LIBMYSQLCLIENT_MINIMUM_VERSION)));
+      }
+    }
+    else {
+      // The libmysqlclient driver supports utf8mb4 starting at version 5.5.3.
+      if (version_compare($version, self::LIBMYSQLCLIENT_MINIMUM_VERSION, '<')) {
+        $this->fail(t("The libmysqlclient driver version %version is less than the minimum required version. Upgrade to libmysqlclient version %libmysqlclient_minimum_version or up, or alternatively switch mysql drivers to MySQLnd version %mysqlnd_minimum_version or up.", array('%version' => $version, '%libmysqlclient_minimum_version' => self::LIBMYSQLCLIENT_MINIMUM_VERSION, '%mysqlnd_minimum_version' => self::MYSQLND_MINIMUM_VERSION)));
+      }
+    }
+  }
+
+}
diff --git a/core/drivers/mysql/src/Merge.php b/core/drivers/mysql/src/Merge.php
new file mode 100644
index 0000000..a7e2670
--- /dev/null
+++ b/core/drivers/mysql/src/Merge.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Merge.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Merge.
+=======
+ * Contains Drupal\mysql\Merge
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Merge.php
+ */
+
+namespace Drupal\mysql;
+
+use Drupal\Core\Database\Query\Merge as QueryMerge;
+
+class Merge extends QueryMerge { }
diff --git a/core/drivers/mysql/src/Schema.php b/core/drivers/mysql/src/Schema.php
new file mode 100644
index 0000000..d38795a
--- /dev/null
+++ b/core/drivers/mysql/src/Schema.php
@@ -0,0 +1,606 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Schema.
+=======
+ * Contains Drupal\mysql\Schema
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Schema.php
+ */
+
+namespace Drupal\mysql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Database\SchemaException;
+use Drupal\Core\Database\SchemaObjectExistsException;
+use Drupal\Core\Database\SchemaObjectDoesNotExistException;
+use Drupal\Core\Database\Schema as DatabaseSchema;
+use Drupal\Component\Utility\Unicode;
+
+/**
+ * @addtogroup schemaapi
+ * @{
+ */
+
+class Schema extends DatabaseSchema {
+
+  /**
+   * Maximum length of a table comment in MySQL.
+   */
+  const COMMENT_MAX_TABLE = 60;
+
+  /**
+   * Maximum length of a column comment in MySQL.
+   */
+  const COMMENT_MAX_COLUMN = 255;
+
+  /**
+   * @var array
+   *   List of MySQL string types.
+   */
+  protected $mysqlStringTypes = array(
+    'VARCHAR',
+    'CHAR',
+    'TINYTEXT',
+    'MEDIUMTEXT',
+    'LONGTEXT',
+    'TEXT',
+  );
+
+  /**
+   * Get information about the table and database name from the prefix.
+   *
+   * @return
+   *   A keyed array with information about the database, table name and prefix.
+   */
+  protected function getPrefixInfo($table = 'default', $add_prefix = TRUE) {
+    $info = array('prefix' => $this->connection->tablePrefix($table));
+    if ($add_prefix) {
+      $table = $info['prefix'] . $table;
+    }
+    if (($pos = strpos($table, '.')) !== FALSE) {
+      $info['database'] = substr($table, 0, $pos);
+      $info['table'] = substr($table, ++$pos);
+    }
+    else {
+      $info['database'] = $this->connection->getConnectionOptions()['database'];
+      $info['table'] = $table;
+    }
+    return $info;
+  }
+
+  /**
+   * Build a condition to match a table name against a standard information_schema.
+   *
+   * MySQL uses databases like schemas rather than catalogs so when we build
+   * a condition to query the information_schema.tables, we set the default
+   * database as the schema unless specified otherwise, and exclude table_catalog
+   * from the condition criteria.
+   */
+  protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) {
+    $table_info = $this->getPrefixInfo($table_name, $add_prefix);
+
+    $condition = new Condition('AND');
+    $condition->condition('table_schema', $table_info['database']);
+    $condition->condition('table_name', $table_info['table'], $operator);
+    return $condition;
+  }
+
+  /**
+   * Generate SQL to create a new table from a Drupal schema definition.
+   *
+   * @param $name
+   *   The name of the table to create.
+   * @param $table
+   *   A Schema API table definition array.
+   * @return
+   *   An array of SQL statements to create the table.
+   */
+  protected function createTableSql($name, $table) {
+    $info = $this->connection->getConnectionOptions();
+
+    // Provide defaults if needed.
+    $table += array(
+      'mysql_engine' => 'InnoDB',
+      'mysql_character_set' => 'utf8mb4',
+    );
+
+    $sql = "CREATE TABLE {" . $name . "} (\n";
+
+    // Add the SQL statement for each field.
+    foreach ($table['fields'] as $field_name => $field) {
+      $sql .= $this->createFieldSql($field_name, $this->processField($field)) . ", \n";
+    }
+
+    // Process keys & indexes.
+    $keys = $this->createKeysSql($table);
+    if (count($keys)) {
+      $sql .= implode(", \n", $keys) . ", \n";
+    }
+
+    // Remove the last comma and space.
+    $sql = substr($sql, 0, -3) . "\n) ";
+
+    $sql .= 'ENGINE = ' . $table['mysql_engine'] . ' DEFAULT CHARACTER SET ' . $table['mysql_character_set'];
+    // By default, MySQL uses the default collation for new tables, which is
+    // 'utf8mb4_general_ci' for utf8mb4. If an alternate collation has been
+    // set, it needs to be explicitly specified.
+    // @see DatabaseConnection_mysql
+    if (!empty($info['collation'])) {
+      $sql .= ' COLLATE ' . $info['collation'];
+    }
+
+    // Add table comment.
+    if (!empty($table['description'])) {
+      $sql .= ' COMMENT ' . $this->prepareComment($table['description'], self::COMMENT_MAX_TABLE);
+    }
+
+    return array($sql);
+  }
+
+  /**
+   * Create an SQL string for a field to be used in table creation or alteration.
+   *
+   * Before passing a field out of a schema definition into this function it has
+   * to be processed by _db_process_field().
+   *
+   * @param string $name
+   *   Name of the field.
+   * @param array $spec
+   *   The field specification, as per the schema data structure format.
+   */
+  protected function createFieldSql($name, $spec) {
+    $sql = "`" . $name . "` " . $spec['mysql_type'];
+
+    if (in_array($spec['mysql_type'], $this->mysqlStringTypes)) {
+      if (isset($spec['length'])) {
+        $sql .= '(' . $spec['length'] . ')';
+      }
+      if (!empty($spec['binary'])) {
+        $sql .= ' BINARY';
+      }
+      // Note we check for the "type" key here. "mysql_type" is VARCHAR:
+      if (isset($spec['type']) && $spec['type'] == 'varchar_ascii') {
+        $sql .= ' CHARACTER SET ascii COLLATE ascii_general_ci';
+      }
+    }
+    elseif (isset($spec['precision']) && isset($spec['scale'])) {
+      $sql .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
+    }
+
+    if (!empty($spec['unsigned'])) {
+      $sql .= ' unsigned';
+    }
+
+    if (isset($spec['not null'])) {
+      if ($spec['not null']) {
+        $sql .= ' NOT NULL';
+      }
+      else {
+        $sql .= ' NULL';
+      }
+    }
+
+    if (!empty($spec['auto_increment'])) {
+      $sql .= ' auto_increment';
+    }
+
+    // $spec['default'] can be NULL, so we explicitly check for the key here.
+    if (array_key_exists('default', $spec)) {
+      $sql .= ' DEFAULT ' . $this->escapeDefaultValue($spec['default']);
+    }
+
+    if (empty($spec['not null']) && !isset($spec['default'])) {
+      $sql .= ' DEFAULT NULL';
+    }
+
+    // Add column comment.
+    if (!empty($spec['description'])) {
+      $sql .= ' COMMENT ' . $this->prepareComment($spec['description'], self::COMMENT_MAX_COLUMN);
+    }
+
+    return $sql;
+  }
+
+  /**
+   * Set database-engine specific properties for a field.
+   *
+   * @param $field
+   *   A field description array, as specified in the schema documentation.
+   */
+  protected function processField($field) {
+
+    if (!isset($field['size'])) {
+      $field['size'] = 'normal';
+    }
+
+    // Set the correct database-engine specific datatype.
+    // In case one is already provided, force it to uppercase.
+    if (isset($field['mysql_type'])) {
+      $field['mysql_type'] = Unicode::strtoupper($field['mysql_type']);
+    }
+    else {
+      $map = $this->getFieldTypeMap();
+      $field['mysql_type'] = $map[$field['type'] . ':' . $field['size']];
+    }
+
+    if (isset($field['type']) && $field['type'] == 'serial') {
+      $field['auto_increment'] = TRUE;
+    }
+
+    return $field;
+  }
+
+  public function getFieldTypeMap() {
+    // Put :normal last so it gets preserved by array_flip. This makes
+    // it much easier for modules (such as schema.module) to map
+    // database types back into schema types.
+    // $map does not use drupal_static as its value never changes.
+    static $map = array(
+      'varchar_ascii:normal' => 'VARCHAR',
+
+      'varchar:normal'  => 'VARCHAR',
+      'char:normal'     => 'CHAR',
+
+      'text:tiny'       => 'TINYTEXT',
+      'text:small'      => 'TINYTEXT',
+      'text:medium'     => 'MEDIUMTEXT',
+      'text:big'        => 'LONGTEXT',
+      'text:normal'     => 'TEXT',
+
+      'serial:tiny'     => 'TINYINT',
+      'serial:small'    => 'SMALLINT',
+      'serial:medium'   => 'MEDIUMINT',
+      'serial:big'      => 'BIGINT',
+      'serial:normal'   => 'INT',
+
+      'int:tiny'        => 'TINYINT',
+      'int:small'       => 'SMALLINT',
+      'int:medium'      => 'MEDIUMINT',
+      'int:big'         => 'BIGINT',
+      'int:normal'      => 'INT',
+
+      'float:tiny'      => 'FLOAT',
+      'float:small'     => 'FLOAT',
+      'float:medium'    => 'FLOAT',
+      'float:big'       => 'DOUBLE',
+      'float:normal'    => 'FLOAT',
+
+      'numeric:normal'  => 'DECIMAL',
+
+      'blob:big'        => 'LONGBLOB',
+      'blob:normal'     => 'BLOB',
+    );
+    return $map;
+  }
+
+  protected function createKeysSql($spec) {
+    $keys = array();
+
+    if (!empty($spec['primary key'])) {
+      $keys[] = 'PRIMARY KEY (' . $this->createKeySql($spec['primary key']) . ')';
+    }
+    if (!empty($spec['unique keys'])) {
+      foreach ($spec['unique keys'] as $key => $fields) {
+        $keys[] = 'UNIQUE KEY `' . $key . '` (' . $this->createKeySql($fields) . ')';
+      }
+    }
+    if (!empty($spec['indexes'])) {
+      $indexes = $this->getNormalizedIndexes($spec);
+      foreach ($indexes as $index => $fields) {
+        $keys[] = 'INDEX `' . $index . '` (' . $this->createKeySql($fields) . ')';
+      }
+    }
+
+    return $keys;
+  }
+
+  /**
+   * Gets normalized indexes from a table specification.
+   *
+   * Shortens indexes to 191 characters if they apply to utf8mb4-encoded
+   * fields, in order to comply with the InnoDB index limitation of 756 bytes.
+   *
+   * @param array $spec
+   *   The table specification.
+   *
+   * @return array
+   *   List of shortened indexes.
+   *
+   * @throws \Drupal\Core\Database\SchemaException
+   *   Thrown if field specification is missing.
+   */
+  protected function getNormalizedIndexes(array $spec) {
+    $indexes = isset($spec['indexes']) ? $spec['indexes'] : [];
+    foreach ($indexes as $index_name => $index_fields) {
+      foreach ($index_fields as $index_key => $index_field) {
+        // Get the name of the field from the index specification.
+        $field_name = is_array($index_field) ? $index_field[0] : $index_field;
+        // Check whether the field is defined in the table specification.
+        if (isset($spec['fields'][$field_name])) {
+          // Get the MySQL type from the processed field.
+          $mysql_field = $this->processField($spec['fields'][$field_name]);
+          if (in_array($mysql_field['mysql_type'], $this->mysqlStringTypes)) {
+            // Check whether we need to shorten the index.
+            if ((!isset($mysql_field['type']) || $mysql_field['type'] != 'varchar_ascii') && (!isset($mysql_field['length']) || $mysql_field['length'] > 191)) {
+              // Limit the index length to 191 characters.
+              $this->shortenIndex($indexes[$index_name][$index_key]);
+            }
+          }
+        }
+        else {
+          throw new SchemaException("MySQL needs the '$field_name' field specification in order to normalize the '$index_name' index");
+        }
+      }
+    }
+    return $indexes;
+  }
+
+  /**
+   * Helper function for normalizeIndexes().
+   *
+   * Shortens an index to 191 characters.
+   *
+   * @param array $index
+   *   The index array to be used in createKeySql.
+   *
+   * @see Drupal\Core\Database\Driver\mysql\Schema::createKeySql()
+   * @see Drupal\Core\Database\Driver\mysql\Schema::normalizeIndexes()
+   */
+  protected function shortenIndex(&$index) {
+    if (is_array($index)) {
+      if ($index[1] > 191) {
+        $index[1] = 191;
+      }
+    }
+    else {
+      $index = array($index, 191);
+    }
+  }
+
+  protected function createKeySql($fields) {
+    $return = array();
+    foreach ($fields as $field) {
+      if (is_array($field)) {
+        $return[] = '`' . $field[0] . '`(' . $field[1] . ')';
+      }
+      else {
+        $return[] = '`' . $field . '`';
+      }
+    }
+    return implode(', ', $return);
+  }
+
+  public function renameTable($table, $new_name) {
+    if (!$this->tableExists($table)) {
+      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 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);
+    return $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO `' . $info['table'] . '`');
+  }
+
+  public function dropTable($table) {
+    if (!$this->tableExists($table)) {
+      return FALSE;
+    }
+
+    $this->connection->query('DROP TABLE {' . $table . '}');
+    return TRUE;
+  }
+
+  public function addField($table, $field, $spec, $keys_new = array()) {
+    if (!$this->tableExists($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 SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
+    }
+
+    $fixnull = FALSE;
+    if (!empty($spec['not null']) && !isset($spec['default'])) {
+      $fixnull = TRUE;
+      $spec['not null'] = FALSE;
+    }
+    $query = 'ALTER TABLE {' . $table . '} ADD ';
+    $query .= $this->createFieldSql($field, $this->processField($spec));
+    if ($keys_sql = $this->createKeysSql($keys_new)) {
+      $query .= ', ADD ' . implode(', ADD ', $keys_sql);
+    }
+    $this->connection->query($query);
+    if (isset($spec['initial'])) {
+      $this->connection->update($table)
+        ->fields(array($field => $spec['initial']))
+        ->execute();
+    }
+    if ($fixnull) {
+      $spec['not null'] = TRUE;
+      $this->changeField($table, $field, $field, $spec);
+    }
+  }
+
+  public function dropField($table, $field) {
+    if (!$this->fieldExists($table, $field)) {
+      return FALSE;
+    }
+
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP `' . $field . '`');
+    return TRUE;
+  }
+
+  public function fieldSetDefault($table, $field, $default) {
+    if (!$this->fieldExists($table, $field)) {
+      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
+    }
+
+    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN `' . $field . '` SET DEFAULT ' . $this->escapeDefaultValue($default));
+  }
+
+  public function fieldSetNoDefault($table, $field) {
+    if (!$this->fieldExists($table, $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');
+  }
+
+  public function indexExists($table, $name) {
+    // Returns one row for each column in the index. Result is string or FALSE.
+    // Details at http://dev.mysql.com/doc/refman/5.0/en/show-index.html
+    $row = $this->connection->query('SHOW INDEX FROM {' . $table . '} WHERE key_name = ' . $this->connection->quote($name))->fetchAssoc();
+    return isset($row['Key_name']);
+  }
+
+  public function addPrimaryKey($table, $fields) {
+    if (!$this->tableExists($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 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) . ')');
+  }
+
+  public function dropPrimaryKey($table) {
+    if (!$this->indexExists($table, 'PRIMARY')) {
+      return FALSE;
+    }
+
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP PRIMARY KEY');
+    return TRUE;
+  }
+
+  public function addUniqueKey($table, $name, $fields) {
+    if (!$this->tableExists($table)) {
+      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 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) . ')');
+  }
+
+  public function dropUniqueKey($table, $name) {
+    if (!$this->indexExists($table, $name)) {
+      return FALSE;
+    }
+
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP KEY `' . $name . '`');
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addIndex($table, $name, $fields, array $spec) {
+    if (!$this->tableExists($table)) {
+      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 SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
+    }
+
+    $spec['indexes'][$name] = $fields;
+    $indexes = $this->getNormalizedIndexes($spec);
+
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD INDEX `' . $name . '` (' . $this->createKeySql($indexes[$name]) . ')');
+  }
+
+  public function dropIndex($table, $name) {
+    if (!$this->indexExists($table, $name)) {
+      return FALSE;
+    }
+
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP INDEX `' . $name . '`');
+    return TRUE;
+  }
+
+  public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
+    if (!$this->fieldExists($table, $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 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));
+    if ($keys_sql = $this->createKeysSql($keys_new)) {
+      $sql .= ', ADD ' . implode(', ADD ', $keys_sql);
+    }
+    $this->connection->query($sql);
+  }
+
+  public function prepareComment($comment, $length = NULL) {
+    // Truncate comment to maximum comment length.
+    if (isset($length)) {
+      // Add table prefixes before truncating.
+      $comment = Unicode::truncate($this->connection->prefixTables($comment), $length, TRUE, TRUE);
+    }
+
+    return $this->connection->quote($comment);
+  }
+
+  /**
+   * Retrieve a table or column comment.
+   */
+  public function getComment($table, $column = NULL) {
+    $condition = $this->buildTableNameCondition($table);
+    if (isset($column)) {
+      $condition->condition('column_name', $column);
+      $condition->compile($this->connection, $this);
+      // Don't use {} around information_schema.columns table.
+      return $this->connection->query("SELECT column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField();
+    }
+    $condition->compile($this->connection, $this);
+    // Don't use {} around information_schema.tables table.
+    $comment = $this->connection->query("SELECT table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField();
+    // Work-around for MySQL 5.0 bug http://bugs.mysql.com/bug.php?id=11379
+    return preg_replace('/; InnoDB free:.*$/', '', $comment);
+  }
+
+  public function tableExists($table) {
+    // The information_schema table is very slow to query under MySQL 5.0.
+    // Instead, we try to select from the table in question.  If it fails,
+    // the most likely reason is that it does not exist. That is dramatically
+    // faster than using information_schema.
+    // @link http://bugs.mysql.com/bug.php?id=19588
+    // @todo This override should be removed once we require a version of MySQL
+    //   that has that bug fixed.
+    try {
+      $this->connection->queryRange("SELECT 1 FROM {" . $table . "}", 0, 1);
+      return TRUE;
+    }
+    catch (\Exception $e) {
+      return FALSE;
+    }
+  }
+
+  public function fieldExists($table, $column) {
+    // The information_schema table is very slow to query under MySQL 5.0.
+    // Instead, we try to select from the table and field in question. If it
+    // fails, the most likely reason is that it does not exist. That is
+    // dramatically faster than using information_schema.
+    // @link http://bugs.mysql.com/bug.php?id=19588
+    // @todo This override should be removed once we require a version of MySQL
+    //   that has that bug fixed.
+    try {
+      $this->connection->queryRange("SELECT $column FROM {" . $table . "}", 0, 1);
+      return TRUE;
+    }
+    catch (\Exception $e) {
+      return FALSE;
+    }
+  }
+
+}
+
+/**
+ * @} End of "addtogroup schemaapi".
+ */
diff --git a/core/drivers/mysql/src/Select.php b/core/drivers/mysql/src/Select.php
new file mode 100644
index 0000000..ba848c4
--- /dev/null
+++ b/core/drivers/mysql/src/Select.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Select.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Select.
+=======
+ * Contains Drupal\mysql\Select
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Select.php
+ */
+
+namespace Drupal\mysql;
+
+use Drupal\Core\Database\Query\Select as QuerySelect;
+
+class Select extends QuerySelect { }
diff --git a/core/drivers/mysql/src/Transaction.php b/core/drivers/mysql/src/Transaction.php
new file mode 100644
index 0000000..a7c3245
--- /dev/null
+++ b/core/drivers/mysql/src/Transaction.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Transaction.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Transaction.
+=======
+ * Contains Drupal\mysql\Transaction
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Transaction.php
+ */
+
+namespace Drupal\mysql;
+
+use Drupal\Core\Database\Transaction as DatabaseTransaction;
+
+class Transaction extends DatabaseTransaction { }
diff --git a/core/drivers/mysql/src/Truncate.php b/core/drivers/mysql/src/Truncate.php
new file mode 100644
index 0000000..7951992
--- /dev/null
+++ b/core/drivers/mysql/src/Truncate.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Truncate.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Truncate.
+=======
+ * Contains Drupal\mysql\Truncate
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Truncate.php
+ */
+
+namespace Drupal\mysql;
+
+use Drupal\Core\Database\Query\Truncate as QueryTruncate;
+
+class Truncate extends QueryTruncate { }
diff --git a/core/drivers/mysql/src/Update.php b/core/drivers/mysql/src/Update.php
new file mode 100644
index 0000000..fc97339
--- /dev/null
+++ b/core/drivers/mysql/src/Update.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Update.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Update.
+=======
+ * Contains Drupal\mysql\Update
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/mysql/src/Update.php
+ */
+
+namespace Drupal\mysql;
+
+use Drupal\Core\Database\Query\Update as QueryUpdate;
+
+class Update extends QueryUpdate { }
diff --git a/core/drivers/pgsql/pgsql.info.yml b/core/drivers/pgsql/pgsql.info.yml
new file mode 100644
index 0000000..1e994c4
--- /dev/null
+++ b/core/drivers/pgsql/pgsql.info.yml
@@ -0,0 +1,3 @@
+type: driver
+core: 8.x
+name: PostgreSQL
diff --git a/core/drivers/pgsql/src/Connection.php b/core/drivers/pgsql/src/Connection.php
new file mode 100644
index 0000000..d5e6e32
--- /dev/null
+++ b/core/drivers/pgsql/src/Connection.php
@@ -0,0 +1,410 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Connection.
+=======
+ * Contains Drupal\pgsql\Connection
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Connection.php
+ */
+
+namespace Drupal\pgsql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection as DatabaseConnection;
+use Drupal\Core\Database\DatabaseNotFoundException;
+use Drupal\Core\Database\StatementInterface;
+use Drupal\Core\Database\IntegrityConstraintViolationException;
+use Drupal\Core\Database\DatabaseExceptionWrapper;
+
+/**
+ * @addtogroup database
+ * @{
+ */
+
+class Connection extends DatabaseConnection {
+
+  /**
+   * The name by which to obtain a lock for retrieve the next insert id.
+   */
+  const POSTGRESQL_NEXTID_LOCK = 1000;
+
+  /**
+   * Error code for "Unknown database" error.
+   */
+  const DATABASE_NOT_FOUND = 7;
+
+  /**
+   * The list of PostgreSQL reserved key words.
+   *
+   * @see http://www.postgresql.org/docs/9.4/static/sql-keywords-appendix.html
+   */
+  protected $postgresqlReservedKeyWords = ['all', 'analyse', 'analyze', 'and',
+  'any', 'array', 'as', 'asc', 'asymmetric', 'authorization', 'binary', 'both',
+  'case', 'cast', 'check', 'collate', 'collation', 'column', 'concurrently',
+  'constraint', 'create', 'cross', 'current_catalog', 'current_date',
+  'current_role', 'current_schema', 'current_time', 'current_timestamp',
+  'current_user', 'default', 'deferrable', 'desc', 'distinct', 'do', 'else',
+  'end', 'except', 'false', 'fetch', 'for', 'foreign', 'freeze', 'from', 'full',
+  'grant', 'group', 'having', 'ilike', 'in', 'initially', 'inner', 'intersect',
+  'into', 'is', 'isnull', 'join', 'lateral', 'leading', 'left', 'like', 'limit',
+  'localtime', 'localtimestamp', 'natural', 'not', 'notnull', 'null', 'offset',
+  'on', 'only', 'or', 'order', 'outer', 'over', 'overlaps', 'placing',
+  'primary', 'references', 'returning', 'right', 'select', 'session_user',
+  'similar', 'some', 'symmetric', 'table', 'then', 'to', 'trailing', 'true',
+  'union', 'unique', 'user', 'using', 'variadic', 'verbose', 'when', 'where',
+  'window', 'with'];
+
+  /**
+   * Constructs a connection object.
+   */
+  public function __construct(\PDO $connection, array $connection_options) {
+    parent::__construct($connection, $connection_options);
+
+    // This driver defaults to transaction support, except if explicitly passed FALSE.
+    $this->transactionSupport = !isset($connection_options['transactions']) || ($connection_options['transactions'] !== FALSE);
+
+    // Transactional DDL is always available in PostgreSQL,
+    // but we'll only enable it if standard transactions are.
+    $this->transactionalDDLSupport = $this->transactionSupport;
+
+    $this->connectionOptions = $connection_options;
+
+    // Force PostgreSQL to use the UTF-8 character set by default.
+    $this->connection->exec("SET NAMES 'UTF8'");
+
+    // Execute PostgreSQL init_commands.
+    if (isset($connection_options['init_commands'])) {
+      $this->connection->exec(implode('; ', $connection_options['init_commands']));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function open(array &$connection_options = array()) {
+    // Default to TCP connection on port 5432.
+    if (empty($connection_options['port'])) {
+      $connection_options['port'] = 5432;
+    }
+
+    // PostgreSQL in trust mode doesn't require a password to be supplied.
+    if (empty($connection_options['password'])) {
+      $connection_options['password'] = NULL;
+    }
+    // If the password contains a backslash it is treated as an escape character
+    // http://bugs.php.net/bug.php?id=53217
+    // so backslashes in the password need to be doubled up.
+    // The bug was reported against pdo_pgsql 1.0.2, backslashes in passwords
+    // will break on this doubling up when the bug is fixed, so check the version
+    //elseif (phpversion('pdo_pgsql') < 'version_this_was_fixed_in') {
+    else {
+      $connection_options['password'] = str_replace('\\', '\\\\', $connection_options['password']);
+    }
+
+    $connection_options['database'] = (!empty($connection_options['database']) ? $connection_options['database'] : 'template1');
+    $dsn = 'pgsql:host=' . $connection_options['host'] . ' dbname=' . $connection_options['database'] . ' port=' . $connection_options['port'];
+
+    // Allow PDO options to be overridden.
+    $connection_options += array(
+      'pdo' => array(),
+    );
+    $connection_options['pdo'] += array(
+      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
+      // Prepared statements are most effective for performance when queries
+      // are recycled (used several times). However, if they are not re-used,
+      // prepared statements become inefficient. Since most of Drupal's
+      // prepared queries are not re-used, it should be faster to emulate
+      // the preparation than to actually ready statements for re-use. If in
+      // doubt, reset to FALSE and measure performance.
+      \PDO::ATTR_EMULATE_PREPARES => TRUE,
+      // Convert numeric values to strings when fetching.
+      \PDO::ATTR_STRINGIFY_FETCHES => TRUE,
+    );
+    $pdo = new \PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
+
+    return $pdo;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query($query, array $args = array(), $options = array()) {
+    $options += $this->defaultOptions();
+
+    // The PDO PostgreSQL driver has a bug which doesn't type cast booleans
+    // correctly when parameters are bound using associative arrays.
+    // @see http://bugs.php.net/bug.php?id=48383
+    foreach ($args as &$value) {
+      if (is_bool($value)) {
+        $value = (int) $value;
+      }
+    }
+
+    return parent::query($query, $args, $options);
+  }
+
+  public function prepareQuery($query) {
+    // mapConditionOperator converts LIKE operations to ILIKE for consistency
+    // with MySQL. However, Postgres does not support ILIKE on bytea (blobs)
+    // fields.
+    // To make the ILIKE operator work, we type-cast bytea fields into text.
+    // @todo This workaround only affects bytea fields, but the involved field
+    //   types involved in the query are unknown, so there is no way to
+    //   conditionally execute this for affected queries only.
+    return parent::prepareQuery(preg_replace('/ ([^ ]+) +(I*LIKE|NOT +I*LIKE) /i', ' ${1}::text ${2} ', $query));
+  }
+
+  public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
+    return $this->query($query . ' LIMIT ' . (int) $count . ' OFFSET ' . (int) $from, $args, $options);
+  }
+
+  public function queryTemporary($query, array $args = array(), array $options = array()) {
+    $tablename = $this->generateTemporaryTableName();
+    $this->query('CREATE TEMPORARY TABLE {' . $tablename . '} AS ' . $query, $args, $options);
+    return $tablename;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function escapeField($field) {
+    $escaped = parent::escapeField($field);
+
+    // Remove any invalid start character.
+    $escaped = preg_replace('/^[^A-Za-z0-9_]/', '', $escaped);
+
+    // The pgsql database driver does not support field names that contain
+    // periods (supported by PostgreSQL server) because this method may be
+    // called by a field with a table alias as part of SQL conditions or
+    // order by statements. This will consider a period as a table alias
+    // identifier, and split the string at the first period.
+    if (preg_match('/^([A-Za-z0-9_]+)"?[.]"?([A-Za-z0-9_.]+)/', $escaped, $parts)) {
+      $table = $parts[1];
+      $column = $parts[2];
+
+      // Use escape alias because escapeField may contain multiple periods that
+      // need to be escaped.
+      $escaped = $this->escapeTable($table) . '.' . $this->escapeAlias($column);
+    }
+    elseif (preg_match('/[A-Z]/', $escaped)) {
+      // Quote the field name for case-sensitivity.
+      $escaped = '"' . $escaped . '"';
+    }
+    elseif (in_array(strtolower($escaped), $this->postgresqlReservedKeyWords)) {
+      // Quote the field name for PostgreSQL reserved key words.
+      $escaped = '"' . $escaped . '"';
+    }
+
+    return $escaped;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function escapeAlias($field) {
+    $escaped = preg_replace('/[^A-Za-z0-9_]+/', '', $field);
+
+    // Escape the alias in quotes for case-sensitivity.
+    if (preg_match('/[A-Z]/', $escaped)) {
+      $escaped = '"' . $escaped . '"';
+    }
+    elseif (in_array(strtolower($escaped), $this->postgresqlReservedKeyWords)) {
+      // Quote the alias name for PostgreSQL reserved key words.
+      $escaped = '"' . $escaped . '"';
+    }
+
+    return $escaped;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function escapeTable($table) {
+    $escaped = parent::escapeTable($table);
+
+    // Quote identifier to make it case-sensitive.
+    if (preg_match('/[A-Z]/', $escaped)) {
+      $escaped = '"' . $escaped . '"';
+    }
+    elseif (in_array(strtolower($escaped), $this->postgresqlReservedKeyWords)) {
+      // Quote the table name for PostgreSQL reserved key words.
+      $escaped = '"' . $escaped . '"';
+    }
+
+    return $escaped;
+  }
+
+  public function driver() {
+    return 'pgsql';
+  }
+
+  public function databaseType() {
+    return 'pgsql';
+  }
+
+  /**
+   * Overrides \Drupal\Core\Database\Connection::createDatabase().
+   *
+   * @param string $database
+   *   The name of the database to create.
+   *
+   * @throws \Drupal\Core\Database\DatabaseNotFoundException
+   */
+  public function createDatabase($database) {
+    // Escape the database name.
+    $database = Database::getConnection()->escapeDatabase($database);
+
+    // If the PECL intl extension is installed, use it to determine the proper
+    // locale.  Otherwise, fall back to en_US.
+    if (class_exists('Locale')) {
+      $locale = \Locale::getDefault();
+    }
+    else {
+      $locale = 'en_US';
+    }
+
+    try {
+      // Create the database and set it as active.
+      $this->connection->exec("CREATE DATABASE $database WITH TEMPLATE template0 ENCODING='utf8' LC_CTYPE='$locale.utf8' LC_COLLATE='$locale.utf8'");
+    }
+    catch (\Exception $e) {
+      throw new DatabaseNotFoundException($e->getMessage());
+    }
+  }
+
+  public function mapConditionOperator($operator) {
+    static $specials = array(
+      // In PostgreSQL, 'LIKE' is case-sensitive. For case-insensitive LIKE
+      // statements, we need to use ILIKE instead.
+      'LIKE' => array('operator' => 'ILIKE'),
+      'LIKE BINARY' => array('operator' => 'LIKE'),
+      'NOT LIKE' => array('operator' => 'NOT ILIKE'),
+      'REGEXP' => array('operator' => '~*'),
+    );
+    return isset($specials[$operator]) ? $specials[$operator] : NULL;
+  }
+
+  /**
+   * Retrieve a the next id in a sequence.
+   *
+   * PostgreSQL has built in sequences. We'll use these instead of inserting
+   * and updating a sequences table.
+   */
+  public function nextId($existing = 0) {
+
+    // Retrieve the name of the sequence. This information cannot be cached
+    // because the prefix may change, for example, like it does in simpletests.
+    $sequence_name = $this->makeSequenceName('sequences', 'value');
+
+    // When PostgreSQL gets a value too small then it will lock the table,
+    // retry the INSERT and if it's still too small then alter the sequence.
+    $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
+    if ($id > $existing) {
+      return $id;
+    }
+
+    // PostgreSQL advisory locks are simply locks to be used by an
+    // application such as Drupal. This will prevent other Drupal processes
+    // from altering the sequence while we are.
+    $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(" . self::POSTGRESQL_NEXTID_LOCK . ")");
+      return $id;
+    }
+
+    // Reset the sequence to a higher value than the existing id.
+    $this->query("ALTER SEQUENCE " . $sequence_name . " RESTART WITH " . ($existing + 1));
+
+    // Retrieve 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(" . self::POSTGRESQL_NEXTID_LOCK . ")");
+
+    return $id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFullQualifiedTableName($table) {
+    $options = $this->getConnectionOptions();
+    $prefix = $this->tablePrefix($table);
+
+    // The fully qualified table name in PostgreSQL is in the form of
+    // <database>.<schema>.<table>, so we have to include the 'public' schema in
+    // the return value.
+    return $options['database'] . '.public.' . $prefix . $table;
+  }
+
+  /**
+   * Add a new savepoint with an unique name.
+   *
+   * The main use for this method is to mimic InnoDB functionality, which
+   * provides an inherent savepoint before any query in a transaction.
+   *
+   * @param $savepoint_name
+   *   A string representing the savepoint name. By default,
+   *   "mimic_implicit_commit" is used.
+   *
+   * @see Drupal\Core\Database\Connection::pushTransaction().
+   */
+  public function addSavepoint($savepoint_name = 'mimic_implicit_commit') {
+    if ($this->inTransaction()) {
+      $this->pushTransaction($savepoint_name);
+    }
+  }
+
+  /**
+   * Release a savepoint by name.
+   *
+   * @param $savepoint_name
+   *   A string representing the savepoint name. By default,
+   *   "mimic_implicit_commit" is used.
+   *
+   * @see Drupal\Core\Database\Connection::popTransaction().
+   */
+  public function releaseSavepoint($savepoint_name = 'mimic_implicit_commit') {
+    if (isset($this->transactionLayers[$savepoint_name])) {
+      $this->popTransaction($savepoint_name);
+    }
+  }
+
+  /**
+   * Rollback a savepoint by name if it exists.
+   *
+   * @param $savepoint_name
+   *   A string representing the savepoint name. By default,
+   *   "mimic_implicit_commit" is used.
+   */
+  public function rollbackSavepoint($savepoint_name = 'mimic_implicit_commit') {
+    if (isset($this->transactionLayers[$savepoint_name])) {
+      $this->rollback($savepoint_name);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function upsert($table, array $options = array()) {
+    // Use the (faster) native Upsert implementation for PostgreSQL >= 9.5.
+    if (version_compare($this->version(), '9.5', '>=')) {
+      $class = $this->getDriverClass('NativeUpsert');
+    }
+    else {
+      $class = $this->getDriverClass('Upsert');
+    }
+
+    return new $class($this, $table, $options);
+  }
+
+}
+
+/**
+ * @} End of "addtogroup database".
+ */
diff --git a/core/drivers/pgsql/src/Delete.php b/core/drivers/pgsql/src/Delete.php
new file mode 100644
index 0000000..a0f0c4a
--- /dev/null
+++ b/core/drivers/pgsql/src/Delete.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Delete.
+=======
+ * Contains Drupal\pgsql\Delete
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Delete.php
+ */
+
+namespace Drupal\pgsql;
+
+use Drupal\Core\Database\Query\Delete as QueryDelete;
+
+class Delete extends QueryDelete {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    $this->connection->addSavepoint();
+    try {
+      $result = parent::execute();
+    }
+    catch (\Exception $e) {
+      $this->connection->rollbackSavepoint();
+      throw $e;
+    }
+    $this->connection->releaseSavepoint();
+
+    return $result;
+  }
+
+}
diff --git a/core/drivers/pgsql/src/Insert.php b/core/drivers/pgsql/src/Insert.php
new file mode 100644
index 0000000..5634f5d
--- /dev/null
+++ b/core/drivers/pgsql/src/Insert.php
@@ -0,0 +1,141 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Insert.
+=======
+ * Contains Drupal\pgsql\Insert
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Insert.php
+ */
+
+namespace Drupal\pgsql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Query\Insert as QueryInsert;
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+class Insert extends QueryInsert {
+
+  public function execute() {
+    if (!$this->preExecute()) {
+      return NULL;
+    }
+
+    $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);
+
+    $max_placeholder = 0;
+    $blobs = array();
+    $blob_count = 0;
+    foreach ($this->insertValues as $insert_values) {
+      foreach ($this->insertFields as $idx => $field) {
+        if (isset($table_information->blob_fields[$field])) {
+          $blobs[$blob_count] = fopen('php://memory', 'a');
+          fwrite($blobs[$blob_count], $insert_values[$idx]);
+          rewind($blobs[$blob_count]);
+
+          $stmt->bindParam(':db_insert_placeholder_' . $max_placeholder++, $blobs[$blob_count], \PDO::PARAM_LOB);
+
+          // Pre-increment is faster in PHP than increment.
+          ++$blob_count;
+        }
+        else {
+          $stmt->bindParam(':db_insert_placeholder_' . $max_placeholder++, $insert_values[$idx]);
+        }
+      }
+      // Check if values for a serial field has been passed.
+      if (!empty($table_information->serial_fields)) {
+        foreach ($table_information->serial_fields as $index => $serial_field) {
+          $serial_key = array_search($serial_field, $this->insertFields);
+          if ($serial_key !== FALSE) {
+            $serial_value = $insert_values[$serial_key];
+
+            // Force $last_insert_id to the specified value. This is only done
+            // if $index is 0.
+            if ($index == 0) {
+              $last_insert_id = $serial_value;
+            }
+            // Sequences must be greater than or equal to 1.
+            if ($serial_value === NULL || !$serial_value) {
+              $serial_value = 1;
+            }
+            // Set the sequence to the bigger value of either the passed
+            // value or the max value of the column. It can happen that another
+            // thread calls nextval() which could lead to a serial number being
+            // used twice. However, trying to insert a value into a serial
+            // column should only be done in very rare cases and is not thread
+            // safe by definition.
+            $this->connection->query("SELECT setval('" . $table_information->sequences[$index] . "', GREATEST(MAX(" . $serial_field . "), :serial_value)) FROM {" . $this->table . "}", array(':serial_value' => (int)$serial_value));
+          }
+        }
+      }
+    }
+    if (!empty($this->fromQuery)) {
+      // bindParam stores only a reference to the variable that is followed when
+      // the statement is executed. We pass $arguments[$key] instead of $value
+      // because the second argument to bindParam is passed by reference and
+      // the foreach statement assigns the element to the existing reference.
+      $arguments = $this->fromQuery->getArguments();
+      foreach ($arguments as $key => $value) {
+        $stmt->bindParam($key, $arguments[$key]);
+      }
+    }
+
+    // PostgreSQL requires the table name to be specified explicitly
+    // when requesting the last insert ID, so we pass that in via
+    // the options array.
+    $options = $this->queryOptions;
+
+    if (!empty($table_information->sequences)) {
+      $options['sequence_name'] = $table_information->sequences[0];
+    }
+    // If there are no sequences then we can't get a last insert id.
+    elseif ($options['return'] == Database::RETURN_INSERT_ID) {
+      $options['return'] = Database::RETURN_NULL;
+    }
+    // Only use the returned last_insert_id if it is not already set.
+    if (!empty($last_insert_id)) {
+      $this->connection->query($stmt, array(), $options);
+    }
+    else {
+      $last_insert_id = $this->connection->query($stmt, array(), $options);
+    }
+
+    // Re-initialize the values array so that we can re-use this query.
+    $this->insertValues = array();
+
+    return $last_insert_id;
+  }
+
+  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);
+
+    $insert_fields = array_map(function($f) { return $this->connection->escapeField($f); }, $insert_fields);
+
+    // 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)) {
+      $insert_fields_string = $insert_fields ? ' (' . implode(', ', $insert_fields) . ') ' : ' ';
+      return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery;
+    }
+
+    $query = $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
+
+    $values = $this->getInsertPlaceholderFragment($this->insertValues, $this->defaultFields);
+    $query .= implode(', ', $values);
+
+    return $query;
+  }
+
+}
diff --git a/core/drivers/pgsql/src/Install/Tasks.php b/core/drivers/pgsql/src/Install/Tasks.php
new file mode 100644
index 0000000..c59f68a
--- /dev/null
+++ b/core/drivers/pgsql/src/Install/Tasks.php
@@ -0,0 +1,290 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Install/Tasks.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Install\Tasks.
+=======
+ * Contains Drupal\pgsql\Install\Tasks
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Install/Tasks.php
+ */
+
+namespace Drupal\pgsql\Install;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Install\Tasks as InstallTasks;
+use Drupal\pgsql\Connection;
+use Drupal\Core\Database\DatabaseNotFoundException;
+
+/**
+ * Specifies installation tasks for PostgreSQL databases.
+ */
+class Tasks extends InstallTasks {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $pdoDriver = 'pgsql';
+
+  /**
+   * Constructs a \Drupal\pgsql\Install\Tasks object.
+   */
+  public function __construct() {
+    $this->tasks[] = array(
+      'function' => 'checkEncoding',
+      'arguments' => array(),
+    );
+    $this->tasks[] = array(
+      'function' => 'checkBinaryOutput',
+      'arguments' => array(),
+    );
+    $this->tasks[] = array(
+      'function' => 'checkStandardConformingStrings',
+      'arguments' => array(),
+    );
+    $this->tasks[] = array(
+      'function' => 'initializeDatabase',
+      'arguments' => array(),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function name() {
+    return t('PostgreSQL');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function minimumVersion() {
+    return '9.1.2';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  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) {
+    // Attempt to create the database if it is not found.
+      if ($e->getCode() == Connection::DATABASE_NOT_FOUND) {
+        // Remove the database string from connection info.
+        $connection_info = Database::getConnectionInfo();
+        $database = $connection_info['default']['database'];
+        unset($connection_info['default']['database']);
+
+        // In order to change the Database::$databaseInfo array, need to remove
+        // the active connection, then re-add it with the new info.
+        Database::removeConnection('default');
+        Database::addConnectionInfo('default', 'default', $connection_info['default']);
+
+        try {
+          // Now, attempt the connection again; if it's successful, attempt to
+          // create the database.
+          Database::getConnection()->createDatabase($database);
+          Database::closeConnection();
+
+          // Now, restore the database config.
+          Database::removeConnection('default');
+          $connection_info['default']['database'] = $database;
+          Database::addConnectionInfo('default', 'default', $connection_info['default']);
+
+          // Check the database connection.
+          Database::getConnection();
+          $this->pass('Drupal can CONNECT to the database ok.');
+        }
+        catch (DatabaseNotFoundException $e) {
+          // Still no dice; probably a permission issue. Raise the error to the
+          // installer.
+          $this->fail(t('Database %database not found. The server reports the following message when attempting to create the database: %error.', array('%database' => $database, '%error' => $e->getMessage())));
+        }
+      }
+      else {
+        // Database connection failed for some other reason than the database
+        // not existing.
+        $this->fail(t('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;
+  }
+
+  /**
+   * Check encoding is UTF8.
+   */
+  protected function checkEncoding() {
+    try {
+      if (db_query('SHOW server_encoding')->fetchField() == 'UTF8') {
+        $this->pass(t('Database is encoded in UTF-8'));
+      }
+      else {
+        $this->fail(t('The %driver database must use %encoding encoding to work with Drupal. Recreate the database with %encoding encoding. See !link for more details.', array(
+          '%encoding' => 'UTF8',
+          '%driver' => $this->name(),
+          '!link' => '<a href="INSTALL.pgsql.txt">INSTALL.pgsql.txt</a>'
+        )));
+      }
+    }
+    catch (\Exception $e) {
+      $this->fail(t('Drupal could not determine the encoding of the database was set to UTF-8'));
+    }
+  }
+
+  /**
+   * Check Binary Output.
+   *
+   * Unserializing does not work on Postgresql 9 when bytea_output is 'hex'.
+   */
+  function checkBinaryOutput() {
+    // PostgreSQL < 9 doesn't support bytea_output, so verify we are running
+    // at least PostgreSQL 9.
+    $database_connection = Database::getConnection();
+    if (version_compare($database_connection->version(), '9') >= 0) {
+      if (!$this->checkBinaryOutputSuccess()) {
+        // First try to alter the database. If it fails, raise an error telling
+        // the user to do it themselves.
+        $connection_options = $database_connection->getConnectionOptions();
+        // It is safe to include the database name directly here, because this
+        // code is only called when a connection to the database is already
+        // established, thus the database name is guaranteed to be a correct
+        // value.
+        $query = "ALTER DATABASE \"" . $connection_options['database'] . "\" SET bytea_output = 'escape';";
+        try {
+          db_query($query);
+        }
+        catch (\Exception $e) {
+          // Ignore possible errors when the user doesn't have the necessary
+          // privileges to ALTER the database.
+        }
+
+        // Close the database connection so that the configuration parameter
+        // is applied to the current connection.
+        db_close();
+
+        // Recheck, if it fails, finally just rely on the end user to do the
+        // right thing.
+        if (!$this->checkBinaryOutputSuccess()) {
+          $replacements = array(
+            '%setting' => 'bytea_output',
+            '%current_value' => 'hex',
+            '%needed_value' => 'escape',
+            '!query' => "<code>" . $query . "</code>",
+          );
+          $this->fail(t("The %setting setting is currently set to '%current_value', but needs to be '%needed_value'. Change this by running the following query: !query", $replacements));
+        }
+      }
+    }
+  }
+
+  /**
+   * Verify that a binary data roundtrip returns the original string.
+   */
+  protected function checkBinaryOutputSuccess() {
+    $bytea_output = db_query("SHOW bytea_output")->fetchField();
+    return ($bytea_output == 'escape');
+  }
+
+  /**
+   * Ensures standard_conforming_strings setting is 'on'.
+   *
+   * When standard_conforming_strings setting is 'on' string literals ('...')
+   * treat backslashes literally, as specified in the SQL standard. This allows
+   * Drupal to convert between bytea, text and varchar columns.
+   */
+  public function checkStandardConformingStrings() {
+    $database_connection = Database::getConnection();
+    if (!$this->checkStandardConformingStringsSuccess()) {
+      // First try to alter the database. If it fails, raise an error telling
+      // the user to do it themselves.
+      $connection_options = $database_connection->getConnectionOptions();
+      // It is safe to include the database name directly here, because this
+      // code is only called when a connection to the database is already
+      // established, thus the database name is guaranteed to be a correct
+      // value.
+      $query = "ALTER DATABASE \"" . $connection_options['database'] . "\" SET standard_conforming_strings = 'on';";
+      try {
+        $database_connection->query($query);
+      }
+      catch (\Exception $e) {
+        // Ignore possible errors when the user doesn't have the necessary
+        // privileges to ALTER the database.
+      }
+
+      // Close the database connection so that the configuration parameter
+      // is applied to the current connection.
+      Database::closeConnection();
+
+      // Recheck, if it fails, finally just rely on the end user to do the
+      // right thing.
+      if (!$this->checkStandardConformingStringsSuccess()) {
+        $replacements = array(
+          '%setting' => 'standard_conforming_strings',
+          '%current_value' => 'off',
+          '%needed_value' => 'on',
+          '!query' => "<code>" . $query . "</code>",
+        );
+        $this->fail(t("The %setting setting is currently set to '%current_value', but needs to be '%needed_value'. Change this by running the following query: !query", $replacements));
+      }
+    }
+  }
+
+  /**
+   * Verifies the standard_conforming_strings setting.
+   */
+  protected function checkStandardConformingStringsSuccess() {
+    $standard_conforming_strings = Database::getConnection()->query("SHOW standard_conforming_strings")->fetchField();
+    return ($standard_conforming_strings == 'on');
+  }
+
+  /**
+   * Make PostgreSQL Drupal friendly.
+   */
+  function initializeDatabase() {
+    // We create some functions using global names instead of prefixing them
+    // like we do with table names. This is so that we don't double up if more
+    // than one instance of Drupal is running on a single database. We therefore
+    // avoid trying to create them again in that case.
+    // At the same time checking for the existence of the function fixes
+    // concurrency issues, when both try to update at the same time.
+    try {
+      // Don't use {} around pg_proc table.
+      if (!db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'rand'")->fetchField()) {
+        db_query('CREATE OR REPLACE FUNCTION "rand"() RETURNS float AS
+          \'SELECT random();\'
+          LANGUAGE \'sql\''
+        );
+      }
+
+      if (!db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'substring_index'")->fetchField()) {
+        db_query('CREATE OR REPLACE FUNCTION "substring_index"(text, text, integer) RETURNS text AS
+          \'SELECT array_to_string((string_to_array($1, $2)) [1:$3], $2);\'
+          LANGUAGE \'sql\''
+        );
+      }
+
+      $this->pass(t('PostgreSQL has initialized itself.'));
+    }
+    catch (\Exception $e) {
+      $this->fail(t('Drupal could not be correctly setup with the existing database due to the following error: @error.', ['@error' => $e->getMessage()]));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormOptions(array $database) {
+    $form = parent::getFormOptions($database);
+    if (empty($form['advanced_options']['port']['#default_value'])) {
+      $form['advanced_options']['port']['#default_value'] = '5432';
+    }
+    return $form;
+  }
+}
diff --git a/core/drivers/pgsql/src/Merge.php b/core/drivers/pgsql/src/Merge.php
new file mode 100644
index 0000000..c777195
--- /dev/null
+++ b/core/drivers/pgsql/src/Merge.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/mysql/Merge.php
+ * Contains \Drupal\Core\Database\Driver\mysql\Merge.
+=======
+ * Contains Drupal\pgsql\Merge
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Merge.php
+ */
+
+namespace Drupal\pgsql;
+
+use Drupal\Core\Database\Query\Merge as QueryMerge;
+
+class Merge extends QueryMerge { }
diff --git a/core/drivers/pgsql/src/Schema.php b/core/drivers/pgsql/src/Schema.php
new file mode 100644
index 0000000..0f47747
--- /dev/null
+++ b/core/drivers/pgsql/src/Schema.php
@@ -0,0 +1,859 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Schema.
+=======
+ * Contains Drupal\pgsql\Schema
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Schema.php
+ */
+
+namespace Drupal\pgsql;
+
+use Drupal\Component\Utility\Unicode;
+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;
+
+/**
+ * @addtogroup schemaapi
+ * @{
+ */
+
+class Schema extends DatabaseSchema {
+
+  /**
+   * A cache of information about blob columns and sequences of tables.
+   *
+   * This is collected by DatabaseConnection_pgsql->queryTableInformation(),
+   * by introspecting the database.
+   *
+   * @see DatabaseConnection_pgsql->queryTableInformation()
+   * @var array
+   */
+  protected $tableInformation = array();
+
+  /**
+   * The maximum allowed length for index, primary key and constraint names.
+   *
+   * Value will usually be set to a 63 chars limit but PostgreSQL allows
+   * to higher this value before compiling, so we need to check for that.
+   *
+   * @var integer
+   */
+  protected $maxIdentifierLength;
+
+  /**
+   * Make sure to limit identifiers according to PostgreSQL compiled in length.
+   *
+   * PostgreSQL allows in standard configuration no longer identifiers than 63
+   * chars for table/relation names, indexes, primary keys, and constraints. So
+   * we map all identifiers that are too long to drupal_base64hash_tag, where
+   * tag is one of:
+   *   - idx for indexes
+   *   - key for constraints
+   *   - pkey for primary keys
+   *
+   * @param $identifiers
+   *   The arguments to build the identifier string
+   * @return
+   *   The index/constraint/pkey identifier
+   */
+  protected function ensureIdentifiersLength($identifier) {
+    $args = func_get_args();
+    $info = $this->getPrefixInfo($identifier);
+    $args[0] = $info['table'];
+    $identifierName = implode('__', $args);
+
+    // Retrieve the max identifier length which is usually 63 characters
+    // but can be altered before PostgreSQL is compiled so we need to check.
+    $this->maxIdentifierLength = $this->connection->query("SHOW max_identifier_length")->fetchField();
+
+    if (strlen($identifierName) > $this->maxIdentifierLength) {
+      $saveIdentifier = '"drupal_' . $this->hashBase64($identifierName) . '_' . $args[2] . '"';
+    }
+    else {
+      $saveIdentifier = $identifierName;
+    }
+    return $saveIdentifier;
+  }
+
+  /**
+   * Fetch the list of blobs and sequences used on a table.
+   *
+   * We introspect the database to collect the information required by insert
+   * and update queries.
+   *
+   * @param $table_name
+   *   The non-prefixed name of the table.
+   * @return
+   *   An object with two member variables:
+   *     - 'blob_fields' that lists all the blob fields in the table.
+   *     - 'sequences' that lists the sequences used in that table.
+   */
+  public function queryTableInformation($table) {
+    // Generate a key to reference this table's information on.
+    $key = $this->connection->prefixTables('{' . $table . '}');
+
+    // Take into account that temporary tables are stored in a different schema.
+    // \Drupal\Core\Database\Connection::generateTemporaryTableName() sets the
+    // 'db_temporary_' prefix to all temporary tables.
+    if (strpos($key, '.') === FALSE && strpos($table, 'db_temporary_') === FALSE) {
+      $key = 'public.' . $key;
+    }
+    else {
+      $schema = $this->connection->query('SELECT nspname FROM pg_namespace WHERE oid = pg_my_temp_schema()')->fetchField();
+      $key = $schema . '.' . $key;
+    }
+
+    if (!isset($this->tableInformation[$key])) {
+      // Split the key into schema and table for querying.
+      list($schema, $table_name) = explode('.', $key);
+      $table_information = (object) array(
+        'blob_fields' => array(),
+        'sequences' => array(),
+      );
+      // Don't use {} around information_schema.columns table.
+      $this->connection->addSavepoint();
+
+      try {
+        // Check if the table information exists in the PostgreSQL metadata.
+        $table_information_exists = (bool) $this->connection->query("SELECT 1 FROM pg_class WHERE relname = :table", array(':table' => $table_name))->fetchField();
+
+        // If the table information does not yet exist in the PostgreSQL
+        // metadata, then return the default table information here, so that it
+        // will not be cached.
+        if (!$table_information_exists) {
+          $this->connection->releaseSavepoint();
+          return $table_information;
+        }
+        else {
+          $result = $this->connection->query("SELECT column_name, data_type, column_default FROM information_schema.columns WHERE table_schema = :schema AND table_name = :table AND (data_type = 'bytea' OR (numeric_precision IS NOT NULL AND column_default LIKE :default))", array(
+            ':schema' => $schema,
+            ':table' => $table_name,
+            ':default' => '%nextval%',
+          ));
+        }
+      }
+      catch (\Exception $e) {
+        $this->connection->rollbackSavepoint();
+        throw $e;
+      }
+      $this->connection->releaseSavepoint();
+
+      foreach ($result as $column) {
+        if ($column->data_type == 'bytea') {
+          $table_information->blob_fields[$column->column_name] = TRUE;
+        }
+        elseif (preg_match("/nextval\('([^']+)'/", $column->column_default, $matches)) {
+          // We must know of any sequences in the table structure to help us
+          // return the last insert id. If there is more than 1 sequences the
+          // first one (index 0 of the sequences array) will be used.
+          $table_information->sequences[] = $matches[1];
+          $table_information->serial_fields[] = $column->column_name;
+        }
+      }
+      $this->tableInformation[$key] = $table_information;
+    }
+    return $this->tableInformation[$key];
+  }
+
+  /**
+   * Resets information about table blobs, sequences and serial fields.
+   *
+   * @param $table
+   *   The non-prefixed name of the table.
+   */
+  protected function resetTableInformation($table) {
+    $key = $this->connection->prefixTables('{' . $table . '}');
+    if (strpos($key, '.') === FALSE) {
+      $key = 'public.' . $key;
+    }
+    unset($this->tableInformation[$key]);
+  }
+
+  /**
+   * Fetch the list of CHECK constraints used on a field.
+   *
+   * We introspect the database to collect the information required by field
+   * alteration.
+   *
+   * @param $table
+   *   The non-prefixed name of the table.
+   * @param $field
+   *   The name of the field.
+   * @return
+   *   An array of all the checks for the field.
+   */
+  public function queryFieldInformation($table, $field) {
+    $prefixInfo = $this->getPrefixInfo($table, TRUE);
+
+    // Split the key into schema and table for querying.
+    $schema = $prefixInfo['schema'];
+    $table_name = $prefixInfo['table'];
+
+    $this->connection->addSavepoint();
+
+    try {
+      $checks = $this->connection->query("SELECT conname FROM pg_class cl INNER JOIN pg_constraint co ON co.conrelid = cl.oid INNER JOIN pg_attribute attr ON attr.attrelid = cl.oid AND attr.attnum = ANY (co.conkey) INNER JOIN pg_namespace ns ON cl.relnamespace = ns.oid WHERE co.contype = 'c' AND ns.nspname = :schema AND cl.relname = :table AND attr.attname = :column", array(
+        ':schema' => $schema,
+        ':table' => $table_name,
+        ':column' => $field,
+      ));
+    }
+    catch (\Exception $e) {
+      $this->connection->rollbackSavepoint();
+      throw $e;
+    }
+
+    $this->connection->releaseSavepoint();
+
+    $field_information = $checks->fetchCol();
+
+    return $field_information;
+  }
+
+  /**
+   * Generate SQL to create a new table from a Drupal schema definition.
+   *
+   * @param $name
+   *   The name of the table to create.
+   * @param $table
+   *   A Schema API table definition array.
+   * @return
+   *   An array of SQL statements to create the table.
+   */
+  protected function createTableSql($name, $table) {
+    $sql_fields = array();
+    foreach ($table['fields'] as $field_name => $field) {
+      $sql_fields[] = $this->createFieldSql($field_name, $this->processField($field));
+    }
+
+    $sql_keys = array();
+    if (isset($table['primary key']) && is_array($table['primary key'])) {
+      $sql_keys[] = 'CONSTRAINT ' . $this->ensureIdentifiersLength($name, '', 'pkey') . ' PRIMARY KEY (' . $this->createPrimaryKeySql($table['primary key']) . ')';
+    }
+    if (isset($table['unique keys']) && is_array($table['unique keys'])) {
+      foreach ($table['unique keys'] as $key_name => $key) {
+        $sql_keys[] = 'CONSTRAINT ' . $this->ensureIdentifiersLength($name, $key_name, 'key') . ' UNIQUE (' . implode(', ', $key) . ')';
+      }
+    }
+
+    $sql = "CREATE TABLE {" . $name . "} (\n\t";
+    $sql .= implode(",\n\t", $sql_fields);
+    if (count($sql_keys) > 0) {
+      $sql .= ",\n\t";
+    }
+    $sql .= implode(",\n\t", $sql_keys);
+    $sql .= "\n)";
+    $statements[] = $sql;
+
+    if (isset($table['indexes']) && is_array($table['indexes'])) {
+      foreach ($table['indexes'] as $key_name => $key) {
+        $statements[] = $this->_createIndexSql($name, $key_name, $key);
+      }
+    }
+
+    // Add table comment.
+    if (!empty($table['description'])) {
+      $statements[] = 'COMMENT ON TABLE {' . $name . '} IS ' . $this->prepareComment($table['description']);
+    }
+
+    // Add column comments.
+    foreach ($table['fields'] as $field_name => $field) {
+      if (!empty($field['description'])) {
+        $statements[] = 'COMMENT ON COLUMN {' . $name . '}.' . $field_name . ' IS ' . $this->prepareComment($field['description']);
+      }
+    }
+
+    return $statements;
+  }
+
+  /**
+   * Create an SQL string for a field to be used in table creation or
+   * alteration.
+   *
+   * Before passing a field out of a schema definition into this
+   * function it has to be processed by _db_process_field().
+   *
+   * @param $name
+   *    Name of the field.
+   * @param $spec
+   *    The field specification, as per the schema data structure format.
+   */
+  protected function createFieldSql($name, $spec) {
+    // The PostgreSQL server converts names into lowercase, unless quoted.
+    $sql = '"' . $name . '" ' . $spec['pgsql_type'];
+
+    if (isset($spec['type']) && $spec['type'] == 'serial') {
+      unset($spec['not null']);
+    }
+
+    if (in_array($spec['pgsql_type'], array('varchar', 'character')) && isset($spec['length'])) {
+      $sql .= '(' . $spec['length'] . ')';
+    }
+    elseif (isset($spec['precision']) && isset($spec['scale'])) {
+      $sql .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
+    }
+
+    if (!empty($spec['unsigned'])) {
+      $sql .= " CHECK ($name >= 0)";
+    }
+
+    if (isset($spec['not null'])) {
+      if ($spec['not null']) {
+        $sql .= ' NOT NULL';
+      }
+      else {
+        $sql .= ' NULL';
+      }
+    }
+    if (array_key_exists('default', $spec)) {
+      $default = $this->escapeDefaultValue($spec['default']);
+      $sql .= " default $default";
+    }
+
+    return $sql;
+  }
+
+  /**
+   * Set database-engine specific properties for a field.
+   *
+   * @param $field
+   *   A field description array, as specified in the schema documentation.
+   */
+  protected function processField($field) {
+    if (!isset($field['size'])) {
+      $field['size'] = 'normal';
+    }
+
+    // Set the correct database-engine specific datatype.
+    // In case one is already provided, force it to lowercase.
+    if (isset($field['pgsql_type'])) {
+      $field['pgsql_type'] = Unicode::strtolower($field['pgsql_type']);
+    }
+    else {
+      $map = $this->getFieldTypeMap();
+      $field['pgsql_type'] = $map[$field['type'] . ':' . $field['size']];
+    }
+
+    if (!empty($field['unsigned'])) {
+      // Unsigned datatypes are not supported in PostgreSQL 9.1. In MySQL,
+      // they are used to ensure a positive number is inserted and it also
+      // doubles the maximum integer size that can be stored in a field.
+      // The PostgreSQL schema in Drupal creates a check constraint
+      // to ensure that a value inserted is >= 0. To provide the extra
+      // integer capacity, here, we bump up the column field size.
+      if (!isset($map)) {
+        $map = $this->getFieldTypeMap();
+      }
+      switch ($field['pgsql_type']) {
+        case 'smallint':
+          $field['pgsql_type'] = $map['int:medium'];
+          break;
+        case 'int' :
+          $field['pgsql_type'] = $map['int:big'];
+          break;
+      }
+    }
+    if (isset($field['type']) && $field['type'] == 'serial') {
+      unset($field['not null']);
+    }
+    return $field;
+  }
+
+  /**
+   * This maps a generic data type in combination with its data size
+   * to the engine-specific data type.
+   */
+  function getFieldTypeMap() {
+    // Put :normal last so it gets preserved by array_flip. This makes
+    // it much easier for modules (such as schema.module) to map
+    // database types back into schema types.
+    // $map does not use drupal_static as its value never changes.
+    static $map = array(
+      'varchar_ascii:normal' => 'varchar',
+
+      'varchar:normal' => 'varchar',
+      'char:normal' => 'character',
+
+      'text:tiny' => 'text',
+      'text:small' => 'text',
+      'text:medium' => 'text',
+      'text:big' => 'text',
+      'text:normal' => 'text',
+
+      'int:tiny' => 'smallint',
+      'int:small' => 'smallint',
+      'int:medium' => 'int',
+      'int:big' => 'bigint',
+      'int:normal' => 'int',
+
+      'float:tiny' => 'real',
+      'float:small' => 'real',
+      'float:medium' => 'real',
+      'float:big' => 'double precision',
+      'float:normal' => 'real',
+
+      'numeric:normal' => 'numeric',
+
+      'blob:big' => 'bytea',
+      'blob:normal' => 'bytea',
+
+      'serial:tiny' => 'serial',
+      'serial:small' => 'serial',
+      'serial:medium' => 'serial',
+      'serial:big' => 'bigserial',
+      'serial:normal' => 'serial',
+      );
+    return $map;
+  }
+
+  protected function _createKeySql($fields) {
+    $return = array();
+    foreach ($fields as $field) {
+      if (is_array($field)) {
+        $return[] = 'substr(' . $field[0] . ', 1, ' . $field[1] . ')';
+      }
+      else {
+        $return[] = '"' . $field . '"';
+      }
+    }
+    return implode(', ', $return);
+  }
+
+  /**
+   * Create the SQL expression for primary keys.
+   *
+   * Postgresql does not support key length. It does support fillfactor, but
+   * that requires a separate database lookup for each column in the key. The
+   * key length defined in the schema is ignored.
+   */
+  protected function createPrimaryKeySql($fields) {
+    $return = array();
+    foreach ($fields as $field) {
+      if (is_array($field)) {
+        $return[] = '"' . $field[0] . '"';
+      }
+      else {
+        $return[] = '"' . $field . '"';
+      }
+    }
+    return implode(', ', $return);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function tableExists($table) {
+    $prefixInfo = $this->getPrefixInfo($table, TRUE);
+
+    return (bool) $this->connection->query("SELECT 1 FROM pg_tables WHERE schemaname = :schema AND tablename = :table", array(':schema' => $prefixInfo['schema'], ':table' => $prefixInfo['table']))->fetchField();
+  }
+
+  function renameTable($table, $new_name) {
+    if (!$this->tableExists($table)) {
+      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 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.
+    $old_full_name = $this->connection->prefixTables('{' . $table . '}');
+    list($old_schema, $old_table_name) = strpos($old_full_name, '.') ? explode('.', $old_full_name) : array('public', $old_full_name);
+
+    // Index names and constraint names are global in PostgreSQL, so we need to
+    // rename them when renaming the table.
+    $indexes = $this->connection->query('SELECT indexname FROM pg_indexes WHERE schemaname = :schema AND tablename = :table', array(':schema' => $old_schema, ':table' => $old_table_name));
+
+    foreach ($indexes as $index) {
+      // Get the index type by suffix, e.g. idx/key/pkey
+      $index_type = substr($index->indexname, strrpos($index->indexname, '_') + 1);
+
+      // If the index is already rewritten by ensureIdentifiersLength() to not
+      // exceed the 63 chars limit of PostgreSQL, we need to take care of that.
+      // Example (drupal_Gk7Su_T1jcBHVuvSPeP22_I3Ni4GrVEgTYlIYnBJkro_idx).
+      if (strpos($index->indexname, 'drupal_') !== FALSE) {
+        preg_match('/^drupal_(.*)_' . preg_quote($index_type) . '/', $index->indexname, $matches);
+        $index_name = $matches[1];
+      }
+      else {
+        // Make sure to remove the suffix from index names, because
+        // $this->ensureIdentifiersLength() will add the suffix again and thus
+        // would result in a wrong index name.
+        preg_match('/^' . preg_quote($old_full_name) . '__(.*)__' . preg_quote($index_type) . '/', $index->indexname, $matches);
+        $index_name = $matches[1];
+      }
+      $this->connection->query('ALTER INDEX "' . $index->indexname . '" RENAME TO ' . $this->ensureIdentifiersLength($new_name, $index_name, $index_type) . '');
+    }
+
+    // Ensure the new table name does not include schema syntax.
+    $prefixInfo = $this->getPrefixInfo($new_name);
+
+    // Rename sequences if there's a serial fields.
+    $info = $this->queryTableInformation($table);
+    if (!empty($info->serial_fields)) {
+      foreach ($info->serial_fields as $field) {
+        $old_sequence = $this->prefixNonTable($table, $field, 'seq');
+        $new_sequence = $this->prefixNonTable($new_name, $field, 'seq');
+        $this->connection->query('ALTER SEQUENCE ' . $old_sequence . ' RENAME TO ' . $new_sequence);
+      }
+    }
+    // Now rename the table.
+    $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO ' . $prefixInfo['table']);
+    $this->resetTableInformation($table);
+  }
+
+  public function dropTable($table) {
+    if (!$this->tableExists($table)) {
+      return FALSE;
+    }
+
+    $this->connection->query('DROP TABLE {' . $table . '}');
+    $this->resetTableInformation($table);
+    return TRUE;
+  }
+
+  public function addField($table, $field, $spec, $new_keys = array()) {
+    if (!$this->tableExists($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 SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
+    }
+
+    $fixnull = FALSE;
+    if (!empty($spec['not null']) && !isset($spec['default'])) {
+      $fixnull = TRUE;
+      $spec['not null'] = FALSE;
+    }
+    $query = 'ALTER TABLE {' . $table . '} ADD COLUMN ';
+    $query .= $this->createFieldSql($field, $this->processField($spec));
+    $this->connection->query($query);
+    if (isset($spec['initial'])) {
+      $this->connection->update($table)
+        ->fields(array($field => $spec['initial']))
+        ->execute();
+    }
+    if ($fixnull) {
+      $this->connection->query("ALTER TABLE {" . $table . "} ALTER $field SET NOT NULL");
+    }
+    if (isset($new_keys)) {
+      $this->_createKeys($table, $new_keys);
+    }
+    // Add column comment.
+    if (!empty($spec['description'])) {
+      $this->connection->query('COMMENT ON COLUMN {' . $table . '}.' . $field . ' IS ' . $this->prepareComment($spec['description']));
+    }
+    $this->resetTableInformation($table);
+  }
+
+  public function dropField($table, $field) {
+    if (!$this->fieldExists($table, $field)) {
+      return FALSE;
+    }
+
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP COLUMN "' . $field . '"');
+    $this->resetTableInformation($table);
+    return TRUE;
+  }
+
+  public function fieldSetDefault($table, $field, $default) {
+    if (!$this->fieldExists($table, $field)) {
+      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
+    }
+
+    $default = $this->escapeDefaultValue($default);
+
+    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" SET DEFAULT ' . $default);
+  }
+
+  public function fieldSetNoDefault($table, $field) {
+    if (!$this->fieldExists($table, $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');
+  }
+
+  public function indexExists($table, $name) {
+    // Details http://www.postgresql.org/docs/9.1/interactive/view-pg-indexes.html
+    $index_name = $this->ensureIdentifiersLength($table, $name, 'idx');
+    // Remove leading and trailing quotes because the index name is in a WHERE
+    // clause and not used as an identifier.
+    $index_name = str_replace('"', '', $index_name);
+    return (bool) $this->connection->query("SELECT 1 FROM pg_indexes WHERE indexname = '$index_name'")->fetchField();
+  }
+
+  /**
+   * Helper function: check if a constraint (PK, FK, UK) exists.
+   *
+   * @param string $table
+   *   The name of the table.
+   * @param string $name
+   *   The name of the constraint (typically 'pkey' or '[constraint]__key').
+   *
+   * @return bool
+   *   TRUE if the constraint exists, FALSE otherwise.
+   */
+  public function constraintExists($table, $name) {
+    // ::ensureIdentifiersLength() expects three parameters, although not
+    // explicitly stated in its signature, thus we split our constraint name in
+    // a proper name and a suffix.
+    if ($name == 'pkey') {
+      $suffix = $name;
+      $name = '';
+    }
+    else {
+      $pos = strrpos($name, '__');
+      $suffix = substr($name, $pos + 2);
+      $name = substr($name, 0, $pos);
+    }
+    $constraint_name = $this->ensureIdentifiersLength($table, $name, $suffix);
+    // Remove leading and trailing quotes because the index name is in a WHERE
+    // clause and not used as an identifier.
+    $constraint_name = str_replace('"', '', $constraint_name);
+    return (bool) $this->connection->query("SELECT 1 FROM pg_constraint WHERE conname = '$constraint_name'")->fetchField();
+  }
+
+  public function addPrimaryKey($table, $fields) {
+    if (!$this->tableExists($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 SchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
+    }
+
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD CONSTRAINT ' . $this->ensureIdentifiersLength($table, '', 'pkey') . ' PRIMARY KEY (' . $this->createPrimaryKeySql($fields) . ')');
+    $this->resetTableInformation($table);
+  }
+
+  public function dropPrimaryKey($table) {
+    if (!$this->constraintExists($table, 'pkey')) {
+      return FALSE;
+    }
+
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $this->ensureIdentifiersLength($table, '', 'pkey'));
+    $this->resetTableInformation($table);
+    return TRUE;
+  }
+
+  function addUniqueKey($table, $name, $fields) {
+    if (!$this->tableExists($table)) {
+      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 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->ensureIdentifiersLength($table, $name, 'key') . ' UNIQUE (' . implode(',', $fields) . ')');
+    $this->resetTableInformation($table);
+  }
+
+  public function dropUniqueKey($table, $name) {
+    if (!$this->constraintExists($table, $name . '__key')) {
+      return FALSE;
+    }
+
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $this->ensureIdentifiersLength($table, $name, 'key'));
+    $this->resetTableInformation($table);
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addIndex($table, $name, $fields, array $spec) {
+    if (!$this->tableExists($table)) {
+      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 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));
+    $this->resetTableInformation($table);
+  }
+
+  public function dropIndex($table, $name) {
+    if (!$this->indexExists($table, $name)) {
+      return FALSE;
+    }
+
+    $this->connection->query('DROP INDEX ' . $this->ensureIdentifiersLength($table, $name, 'idx'));
+    $this->resetTableInformation($table);
+    return TRUE;
+  }
+
+  public function changeField($table, $field, $field_new, $spec, $new_keys = array()) {
+    if (!$this->fieldExists($table, $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 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);
+
+    // Type 'serial' is known to PostgreSQL, but only during table creation,
+    // not when altering. Because of that, we create it here as an 'int'. After
+    // we create it we manually re-apply the sequence.
+    if (in_array($spec['pgsql_type'], array('serial', 'bigserial'))) {
+      $field_def = 'int';
+    }
+    else {
+      $field_def = $spec['pgsql_type'];
+    }
+
+    if (in_array($spec['pgsql_type'], array('varchar', 'character', 'text')) && isset($spec['length'])) {
+      $field_def .= '(' . $spec['length'] . ')';
+    }
+    elseif (isset($spec['precision']) && isset($spec['scale'])) {
+      $field_def .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
+    }
+
+    // Remove old check constraints.
+    $field_info = $this->queryFieldInformation($table, $field);
+
+    foreach ($field_info as $check) {
+      $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT "' . $check . '"');
+    }
+
+    // Remove old default.
+    $this->fieldSetNoDefault($table, $field);
+
+    // Convert field type.
+    // Usually, we do this via a simple typecast 'USING fieldname::type'. But
+    // the typecast does not work for conversions to bytea.
+    // @see http://www.postgresql.org/docs/current/static/datatype-binary.html
+    $table_information = $this->queryTableInformation($table);
+    $is_bytea = !empty($table_information->blob_fields[$field]);
+    if ($spec['pgsql_type'] != 'bytea') {
+      if ($is_bytea) {
+        $this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" TYPE ' . $field_def . ' USING convert_from("' . $field . '"' . ", 'UTF8')");
+      }
+      else {
+        $this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" TYPE ' . $field_def . ' USING "' . $field . '"::' . $field_def);
+      }
+    }
+    else {
+      // Do not attempt to convert a field that is bytea already.
+      if (!$is_bytea) {
+        // Convert to a bytea type by using the SQL replace() function to
+        // convert any single backslashes in the field content to double
+        // backslashes ('\' to '\\').
+        $this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" TYPE ' . $field_def . ' USING decode(replace("' . $field . '"' . ", E'\\\\', E'\\\\\\\\'), 'escape');");
+      }
+    }
+
+    if (isset($spec['not null'])) {
+      if ($spec['not null']) {
+        $nullaction = 'SET NOT NULL';
+      }
+      else {
+        $nullaction = 'DROP NOT NULL';
+      }
+      $this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" ' . $nullaction);
+    }
+
+    if (in_array($spec['pgsql_type'], array('serial', 'bigserial'))) {
+      // Type "serial" is known to PostgreSQL, but *only* during table creation,
+      // not when altering. Because of that, the sequence needs to be created
+      // and initialized by hand.
+      $seq = "{" . $table . "}_" . $field_new . "_seq";
+      $this->connection->query("CREATE SEQUENCE " . $seq);
+      // Set sequence to maximal field value to not conflict with existing
+      // entries.
+      $this->connection->query("SELECT setval('" . $seq . "', MAX(\"" . $field . '")) FROM {' . $table . "}");
+      $this->connection->query('ALTER TABLE {' . $table . '} ALTER ' . $field . ' SET DEFAULT nextval(' . $this->connection->quote($seq) . ')');
+    }
+
+    // Rename the column if necessary.
+    if ($field != $field_new) {
+      $this->connection->query('ALTER TABLE {' . $table . '} RENAME "' . $field . '" TO "' . $field_new . '"');
+    }
+
+    // Add unsigned check if necessary.
+    if (!empty($spec['unsigned'])) {
+      $this->connection->query('ALTER TABLE {' . $table . '} ADD CHECK ("' . $field_new . '" >= 0)');
+    }
+
+    // Add default if necessary.
+    if (isset($spec['default'])) {
+      $this->fieldSetDefault($table, $field_new, $spec['default']);
+    }
+
+    // Change description if necessary.
+    if (!empty($spec['description'])) {
+      $this->connection->query('COMMENT ON COLUMN {' . $table . '}."' . $field_new . '" IS ' . $this->prepareComment($spec['description']));
+    }
+
+    if (isset($new_keys)) {
+      $this->_createKeys($table, $new_keys);
+    }
+    $this->resetTableInformation($table);
+  }
+
+  protected function _createIndexSql($table, $name, $fields) {
+    $query = 'CREATE INDEX ' . $this->ensureIdentifiersLength($table, $name, 'idx') . ' ON {' . $table . '} (';
+    $query .= $this->_createKeySql($fields) . ')';
+    return $query;
+  }
+
+  protected function _createKeys($table, $new_keys) {
+    if (isset($new_keys['primary key'])) {
+      $this->addPrimaryKey($table, $new_keys['primary key']);
+    }
+    if (isset($new_keys['unique keys'])) {
+      foreach ($new_keys['unique keys'] as $name => $fields) {
+        $this->addUniqueKey($table, $name, $fields);
+      }
+    }
+    if (isset($new_keys['indexes'])) {
+      foreach ($new_keys['indexes'] as $name => $fields) {
+        // Even though $new_keys is not a full schema it still has 'indexes' and
+        // so is a partial schema. Technically addIndex() doesn't do anything
+        // with it so passing an empty array would work as well.
+        $this->addIndex($table, $name, $fields, $new_keys);
+      }
+    }
+  }
+
+  /**
+   * Retrieve a table or column comment.
+   */
+  public function getComment($table, $column = NULL) {
+    $info = $this->getPrefixInfo($table);
+    // Don't use {} around pg_class, pg_attribute tables.
+    if (isset($column)) {
+      return $this->connection->query('SELECT col_description(oid, attnum) FROM pg_class, pg_attribute WHERE attrelid = oid AND relname = ? AND attname = ?', array($info['table'], $column))->fetchField();
+    }
+    else {
+      return $this->connection->query('SELECT obj_description(oid, ?) FROM pg_class WHERE relname = ?', array('pg_class', $info['table']))->fetchField();
+    }
+  }
+
+  /**
+   * Calculates a base-64 encoded, PostgreSQL-safe sha-256 hash per PostgreSQL
+   * documentation: 4.1. Lexical Structure.
+   *
+   * @param $data
+   *   String to be hashed.
+   * @return string
+   *   A base-64 encoded sha-256 hash, with + and / replaced with _ and any =
+   *   padding characters removed.
+   */
+  protected function hashBase64($data) {
+    $hash = base64_encode(hash('sha256', $data, TRUE));
+    // Modify the hash so it's safe to use in PostgreSQL identifiers.
+    return strtr($hash, array('+' => '_', '/' => '_', '=' => ''));
+  }
+}
+
+/**
+ * @} End of "addtogroup schemaapi".
+ */
diff --git a/core/drivers/pgsql/src/Select.php b/core/drivers/pgsql/src/Select.php
new file mode 100644
index 0000000..c269df6
--- /dev/null
+++ b/core/drivers/pgsql/src/Select.php
@@ -0,0 +1,165 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Select.
+=======
+ * Contains Drupal\pgsql\Select
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Select.php
+ */
+
+namespace Drupal\pgsql;
+
+use Drupal\Core\Database\Query\Select as QuerySelect;
+
+/**
+ * @addtogroup database
+ * @{
+ */
+
+class Select extends QuerySelect {
+
+  public function orderRandom() {
+    $alias = $this->addExpression('RANDOM()', 'random_field');
+    $this->orderBy($alias);
+    return $this;
+  }
+
+  /**
+   * Overrides SelectQuery::orderBy().
+   *
+   * PostgreSQL adheres strictly to the SQL-92 standard and requires that when
+   * using DISTINCT or GROUP BY conditions, fields and expressions that are
+   * ordered on also need to be selected. This is a best effort implementation
+   * to handle the cases that can be automated by adding the field if it is not
+   * yet selected.
+   *
+   * @code
+   *   $query = db_select('example', 'e');
+   *   $query->join('example_revision', 'er', 'e.vid = er.vid');
+   *   $query
+   *     ->distinct()
+   *     ->fields('e')
+   *     ->orderBy('timestamp');
+   * @endcode
+   *
+   * In this query, it is not possible (without relying on the schema) to know
+   * whether timestamp belongs to example_revision and needs to be added or
+   * belongs to node and is already selected. Queries like this will need to be
+   * corrected in the original query by adding an explicit call to
+   * SelectQuery::addField() or SelectQuery::fields().
+   *
+   * Since this has a small performance impact, both by the additional
+   * processing in this function and in the database that needs to return the
+   * additional fields, this is done as an override instead of implementing it
+   * directly in SelectQuery::orderBy().
+   */
+  public function orderBy($field, $direction = 'ASC') {
+    // Only allow ASC and DESC, default to ASC.
+    // Emulate MySQL default behavior to sort NULL values first for ascending,
+    // and last for descending.
+    // @see http://www.postgresql.org/docs/9.3/static/queries-order.html
+    $direction = strtoupper($direction) == 'DESC' ? 'DESC NULLS LAST' : 'ASC NULLS FIRST';
+    $this->order[$field] = $direction;
+
+    if ($this->hasTag('entity_query')) {
+      return $this;
+    }
+
+    // If there is a table alias specified, split it up.
+    if (strpos($field, '.') !== FALSE) {
+      list($table, $table_field) = explode('.', $field);
+    }
+    // Figure out if the field has already been added.
+    foreach ($this->fields as $existing_field) {
+      if (!empty($table)) {
+        // If table alias is given, check if field and table exists.
+        if ($existing_field['table'] == $table && $existing_field['field'] == $table_field) {
+          return $this;
+        }
+      }
+      else {
+        // If there is no table, simply check if the field exists as a field or
+        // an aliased field.
+        if ($existing_field['alias'] == $field) {
+          return $this;
+        }
+      }
+    }
+
+    // Also check expression aliases.
+    foreach ($this->expressions as $expression) {
+      if ($expression['alias'] == $this->connection->escapeAlias($field)) {
+        return $this;
+      }
+    }
+
+    // If a table loads all fields, it can not be added again. It would
+    // result in an ambiguous alias error because that field would be loaded
+    // twice: Once through table_alias.* and once directly. If the field
+    // actually belongs to a different table, it must be added manually.
+    foreach ($this->tables as $table) {
+      if (!empty($table['all_fields'])) {
+        return $this;
+      }
+    }
+
+    // If $field contains an characters which are not allowed in a field name
+    // it is considered an expression, these can't be handled automatically
+    // either.
+    if ($this->connection->escapeField($field) != $field) {
+      return $this;
+    }
+
+    // This is a case that can be handled automatically, add the field.
+    $this->addField(NULL, $field);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addExpression($expression, $alias = NULL, $arguments = array()) {
+    if (empty($alias)) {
+      $alias = 'expression';
+    }
+
+    // This implements counting in the same manner as the parent method.
+    $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' => $this->connection->escapeAlias($alias_candidate),
+      'arguments' => $arguments,
+    );
+
+    return $alias;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    $this->connection->addSavepoint();
+    try {
+      $result = parent::execute();
+    }
+    catch (\Exception $e) {
+      $this->connection->rollbackSavepoint();
+      throw $e;
+    }
+    $this->connection->releaseSavepoint();
+
+    return $result;
+  }
+}
+
+/**
+ * @} End of "addtogroup database".
+ */
diff --git a/core/drivers/pgsql/src/Transaction.php b/core/drivers/pgsql/src/Transaction.php
new file mode 100644
index 0000000..a377efa
--- /dev/null
+++ b/core/drivers/pgsql/src/Transaction.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Transaction.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Transaction.
+=======
+ * Contains Drupal\pgsql\Transaction
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Transaction.php
+ */
+
+namespace Drupal\pgsql;
+
+use Drupal\Core\Database\Transaction as DatabaseTransaction;
+
+class Transaction extends DatabaseTransaction { }
diff --git a/core/drivers/pgsql/src/Truncate.php b/core/drivers/pgsql/src/Truncate.php
new file mode 100644
index 0000000..82515ae
--- /dev/null
+++ b/core/drivers/pgsql/src/Truncate.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Truncate.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Truncate.
+=======
+ * Contains Drupal\pgsql\Truncate
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Truncate.php
+ */
+
+namespace Drupal\pgsql;
+
+use Drupal\Core\Database\Query\Truncate as QueryTruncate;
+
+class Truncate extends QueryTruncate {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    $this->connection->addSavepoint();
+    try {
+      $result = parent::execute();
+    }
+    catch (\Exception $e) {
+      $this->connection->rollbackSavepoint();
+      throw $e;
+    }
+    $this->connection->releaseSavepoint();
+
+    return $result;
+  }
+}
diff --git a/core/drivers/pgsql/src/Update.php b/core/drivers/pgsql/src/Update.php
new file mode 100644
index 0000000..3908f23
--- /dev/null
+++ b/core/drivers/pgsql/src/Update.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/pgsql/Update.php
+ * Contains \Drupal\Core\Database\Driver\pgsql\Update.
+=======
+ * Contains Drupal\pgsql\Update
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/pgsql/src/Update.php
+ */
+
+namespace Drupal\pgsql;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Query\Update as QueryUpdate;
+use Drupal\Core\Database\Query\SelectInterface;
+
+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;
+    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]);
+        }
+      }
+      if ($data['expression'] instanceof SelectInterface) {
+        $data['expression']->compile($this->connection, $this);
+        $select_query_arguments = $data['expression']->arguments();
+        foreach ($select_query_arguments as $placeholder => $argument) {
+          $stmt->bindParam($placeholder, $select_query_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;
+    $options['return'] = Database::RETURN_AFFECTED;
+
+    $this->connection->addSavepoint();
+    try {
+      $result = $this->connection->query($stmt, array(), $options);
+      $this->connection->releaseSavepoint();
+      return $result;
+    }
+    catch (\Exception $e) {
+      $this->connection->rollbackSavepoint();
+      throw $e;
+    }
+  }
+
+}
diff --git a/core/drivers/sqlite/sqlite.info.yml b/core/drivers/sqlite/sqlite.info.yml
new file mode 100644
index 0000000..288dfa4
--- /dev/null
+++ b/core/drivers/sqlite/sqlite.info.yml
@@ -0,0 +1,3 @@
+type: driver
+core: 8.x
+name: SQLite
diff --git a/core/drivers/sqlite/src/Connection.php b/core/drivers/sqlite/src/Connection.php
new file mode 100644
index 0000000..b481deb
--- /dev/null
+++ b/core/drivers/sqlite/src/Connection.php
@@ -0,0 +1,429 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Connection.
+=======
+ * Contains Drupal\sqlite\Connection
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Connection.php
+ */
+
+namespace Drupal\sqlite;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\DatabaseNotFoundException;
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
+=======
+use Drupal\Core\Database\TransactionNoActiveException;
+use Drupal\Core\Database\TransactionNameNonUniqueException;
+use Drupal\Core\Database\TransactionCommitFailedException;
+use Drupal\sqlite\Statement;
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Connection.php
+use Drupal\Core\Database\Connection as DatabaseConnection;
+
+/**
+ * Specific SQLite implementation of DatabaseConnection.
+ */
+class Connection extends DatabaseConnection {
+
+  /**
+   * Error code for "Unable to open database file" error.
+   */
+  const DATABASE_NOT_FOUND = 14;
+
+  /**
+   * Whether or not the active transaction (if any) will be rolled back.
+   *
+   * @var bool
+   */
+  protected $willRollback;
+
+  /**
+   * 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();
+
+  /**
+   * 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 Schema needs to
+   * access it. However, it should not be manually set.
+   *
+   * @var bool
+   */
+  var $tableDropped = FALSE;
+
+  /**
+   * Constructs a \Drupal\sqlite\Connection object.
+   */
+  public function __construct(\PDO $connection, array $connection_options) {
+    // We don't need a specific PDOStatement class here, we simulate it in
+    // static::prepare().
+    $this->statementClass = NULL;
+
+    parent::__construct($connection, $connection_options);
+
+    // This driver defaults to transaction support, except if explicitly passed FALSE.
+    $this->transactionSupport = $this->transactionalDDLSupport = !isset($connection_options['transactions']) || $connection_options['transactions'] !== FALSE;
+
+    $this->connectionOptions = $connection_options;
+
+    // Attach one database for each registered prefix.
+    $prefixes = $this->prefixes;
+    foreach ($prefixes as &$prefix) {
+      // Empty prefix means query the main database -- no need to attach anything.
+      if (!empty($prefix)) {
+        // Only attach the database once.
+        if (!isset($this->attachedDatabases[$prefix])) {
+          $this->attachedDatabases[$prefix] = $prefix;
+          if ($connection_options['database'] === ':memory:') {
+            // In memory database use ':memory:' as database name. According to
+            // http://www.sqlite.org/inmemorydb.html it will open a unique
+            // database so attaching it twice is not a problem.
+            $this->query('ATTACH DATABASE :database AS :prefix', array(':database' => $connection_options['database'], ':prefix' => $prefix));
+          }
+          else {
+            $this->query('ATTACH DATABASE :database AS :prefix', array(':database' => $connection_options['database'] . '-' . $prefix, ':prefix' => $prefix));
+          }
+        }
+
+        // Add a ., so queries become prefix.table, which is proper syntax for
+        // querying an attached database.
+        $prefix .= '.';
+      }
+    }
+    // Regenerate the prefixes replacement table.
+    $this->setPrefix($prefixes);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function open(array &$connection_options = array()) {
+    // Allow PDO options to be overridden.
+    $connection_options += array(
+      'pdo' => array(),
+    );
+    $connection_options['pdo'] += array(
+      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
+      // Convert numeric values to strings when fetching.
+      \PDO::ATTR_STRINGIFY_FETCHES => TRUE,
+    );
+    $pdo = new \PDO('sqlite:' . $connection_options['database'], '', '', $connection_options['pdo']);
+
+    // Create functions needed by SQLite.
+    $pdo->sqliteCreateFunction('if', array(__CLASS__, 'sqlFunctionIf'));
+    $pdo->sqliteCreateFunction('greatest', array(__CLASS__, 'sqlFunctionGreatest'));
+    $pdo->sqliteCreateFunction('pow', 'pow', 2);
+    $pdo->sqliteCreateFunction('exp', 'exp', 1);
+    $pdo->sqliteCreateFunction('length', 'strlen', 1);
+    $pdo->sqliteCreateFunction('md5', 'md5', 1);
+    $pdo->sqliteCreateFunction('concat', array(__CLASS__, 'sqlFunctionConcat'));
+    $pdo->sqliteCreateFunction('concat_ws', array(__CLASS__, 'sqlFunctionConcatWs'));
+    $pdo->sqliteCreateFunction('substring', array(__CLASS__, 'sqlFunctionSubstring'), 3);
+    $pdo->sqliteCreateFunction('substring_index', array(__CLASS__, 'sqlFunctionSubstringIndex'), 3);
+    $pdo->sqliteCreateFunction('rand', array(__CLASS__, 'sqlFunctionRand'));
+    $pdo->sqliteCreateFunction('regexp', array(__CLASS__, 'sqlFunctionRegexp'));
+
+    // SQLite does not support the LIKE BINARY operator, so we overload the
+    // non-standard GLOB operator for case-sensitive matching. Another option
+    // would have been to override another non-standard operator, MATCH, but
+    // that does not support the NOT keyword prefix.
+    $pdo->sqliteCreateFunction('glob', array(__CLASS__, 'sqlFunctionLikeBinary'));
+
+    // Create a user-space case-insensitive collation with UTF-8 support.
+    $pdo->sqliteCreateCollation('NOCASE_UTF8', array('Drupal\Component\Utility\Unicode', 'strcasecmp'));
+
+    // Execute sqlite init_commands.
+    if (isset($connection_options['init_commands'])) {
+      $pdo->exec(implode('; ', $connection_options['init_commands']));
+    }
+
+    return $pdo;
+  }
+
+
+  /**
+   * Destructor for the SQLite connection.
+   *
+   * We prune empty databases on destruct, but only if tables have been
+   * dropped. This is especially needed when running the test suite, which
+   * creates and destroy databases several times in a row.
+   */
+  public function __destruct() {
+    if ($this->tableDropped && !empty($this->attachedDatabases)) {
+      foreach ($this->attachedDatabases as $prefix) {
+        // Check if the database is now empty, ignore the internal SQLite tables.
+        try {
+          $count = $this->query('SELECT COUNT(*) FROM ' . $prefix . '.sqlite_master WHERE type = :type AND name NOT LIKE :pattern', array(':type' => 'table', ':pattern' => 'sqlite_%'))->fetchField();
+
+          // We can prune the database file if it doesn't have any tables.
+          if ($count == 0) {
+            // Detaching the database fails at this point, but no other queries
+            // are executed after the connection is destructed so we can simply
+            // remove the database file.
+            unlink($this->connectionOptions['database'] . '-' . $prefix);
+          }
+        }
+        catch (\Exception $e) {
+          // Ignore the exception and continue. There is nothing we can do here
+          // to report the error or fail safe.
+        }
+      }
+    }
+  }
+
+  /**
+   * Gets all the attached databases.
+   *
+   * @return array
+   *   An array of attached database names.
+   *
+   * @see \Drupal\Core\Database\Driver\sqlite\Connection::__construct()
+   */
+  public function getAttachedDatabases() {
+    return $this->attachedDatabases;
+  }
+
+  /**
+   * SQLite compatibility implementation for the IF() SQL function.
+   */
+  public static function sqlFunctionIf($condition, $expr1, $expr2 = NULL) {
+    return $condition ? $expr1 : $expr2;
+  }
+
+  /**
+   * SQLite compatibility implementation for the GREATEST() SQL function.
+   */
+  public static function sqlFunctionGreatest() {
+    $args = func_get_args();
+    foreach ($args as $v) {
+      if (!isset($v)) {
+        unset($args);
+      }
+    }
+    if (count($args)) {
+      return max($args);
+    }
+    else {
+      return NULL;
+    }
+  }
+
+  /**
+   * SQLite compatibility implementation for the CONCAT() SQL function.
+   */
+  public static function sqlFunctionConcat() {
+    $args = func_get_args();
+    return implode('', $args);
+  }
+
+  /**
+   * SQLite compatibility implementation for the CONCAT_WS() SQL function.
+   *
+   * @see http://dev.mysql.com/doc/refman/5.6/en/string-functions.html#function_concat-ws
+   */
+  public static function sqlFunctionConcatWs() {
+    $args = func_get_args();
+    $separator = array_shift($args);
+    // If the separator is NULL, the result is NULL.
+    if ($separator === FALSE || is_null($separator)) {
+      return NULL;
+    }
+    // Skip any NULL values after the separator argument.
+    $args = array_filter($args, function ($value) {
+      return !is_null($value);
+    });
+    return implode($separator, $args);
+  }
+
+  /**
+   * SQLite compatibility implementation for the SUBSTRING() SQL function.
+   */
+  public static function sqlFunctionSubstring($string, $from, $length) {
+    return substr($string, $from - 1, $length);
+  }
+
+  /**
+   * SQLite compatibility implementation for the SUBSTRING_INDEX() SQL function.
+   */
+  public static function sqlFunctionSubstringIndex($string, $delimiter, $count) {
+    // If string is empty, simply return an empty string.
+    if (empty($string)) {
+      return '';
+    }
+    $end = 0;
+    for ($i = 0; $i < $count; $i++) {
+      $end = strpos($string, $delimiter, $end + 1);
+      if ($end === FALSE) {
+        $end = strlen($string);
+      }
+    }
+    return substr($string, 0, $end);
+  }
+
+  /**
+   * SQLite compatibility implementation for the RAND() SQL function.
+   */
+  public static function sqlFunctionRand($seed = NULL) {
+    if (isset($seed)) {
+      mt_srand($seed);
+    }
+    return mt_rand() / mt_getrandmax();
+  }
+
+  /**
+   * SQLite compatibility implementation for the REGEXP SQL operator.
+   *
+   * The REGEXP operator is natively known, but not implemented by default.
+   *
+   * @see http://www.sqlite.org/lang_expr.html#regexp
+   */
+  public static function sqlFunctionRegexp($pattern, $subject) {
+    // preg_quote() cannot be used here, since $pattern may contain reserved
+    // regular expression characters already (such as ^, $, etc). Therefore,
+    // use a rare character as PCRE delimiter.
+    $pattern = '#' . addcslashes($pattern, '#') . '#i';
+    return preg_match($pattern, $subject);
+  }
+
+  /**
+   * SQLite compatibility implementation for the LIKE BINARY SQL operator.
+   *
+   * SQLite supports case-sensitive LIKE operations through the
+   * 'case_sensitive_like' PRAGMA statement, but only for ASCII characters, so
+   * we have to provide our own implementation with UTF-8 support.
+   *
+   * @see https://sqlite.org/pragma.html#pragma_case_sensitive_like
+   * @see https://sqlite.org/lang_expr.html#like
+   */
+  public static function sqlFunctionLikeBinary($pattern, $subject) {
+    // Replace the SQL LIKE wildcard meta-characters with the equivalent regular
+    // expression meta-characters and escape the delimiter that will be used for
+    // matching.
+    $pattern = str_replace(array('%', '_'), array('.*?', '.'), preg_quote($pattern, '/'));
+    return preg_match('/^' . $pattern . '$/', $subject);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepare($statement, array $driver_options = array()) {
+    return new Statement($this->connection, $this, $statement, $driver_options);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function handleQueryException(\PDOException $e, $query, array $args = array(), $options = array()) {
+    // The database schema might be changed by another process in between the
+    // time that the statement was prepared and the time the statement was run
+    // (e.g. usually happens when running tests). In this case, we need to
+    // re-run the query.
+    // @see http://www.sqlite.org/faq.html#q15
+    // @see http://www.sqlite.org/rescode.html#schema
+    if (!empty($e->errorInfo[1]) && $e->errorInfo[1] === 17) {
+      return $this->query($query, $args, $options);
+    }
+
+    parent::handleQueryException($e, $query, $args, $options);
+  }
+
+  public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
+    return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options);
+  }
+
+  public function queryTemporary($query, array $args = array(), array $options = array()) {
+    // Generate a new temporary table name and protect it from prefixing.
+    // SQLite requires that temporary tables to be non-qualified.
+    $tablename = $this->generateTemporaryTableName();
+    $prefixes = $this->prefixes;
+    $prefixes[$tablename] = '';
+    $this->setPrefix($prefixes);
+
+    $this->query('CREATE TEMPORARY TABLE ' . $tablename . ' AS ' . $query, $args, $options);
+    return $tablename;
+  }
+
+  public function driver() {
+    return 'sqlite';
+  }
+
+  public function databaseType() {
+    return 'sqlite';
+  }
+
+  /**
+   * Overrides \Drupal\Core\Database\Connection::createDatabase().
+   *
+   * @param string $database
+   *   The name of the database to create.
+   *
+   * @throws \Drupal\Core\Database\DatabaseNotFoundException
+   */
+  public function createDatabase($database) {
+    // Verify the database is writable.
+    $db_directory = new \SplFileInfo(dirname($database));
+    if (!$db_directory->isDir() && !drupal_mkdir($db_directory->getPathName(), 0755, TRUE)) {
+      throw new DatabaseNotFoundException('Unable to create database directory ' . $db_directory->getPathName());
+    }
+  }
+
+  public function mapConditionOperator($operator) {
+    // We don't want to override any of the defaults.
+    static $specials = array(
+      'LIKE' => array('postfix' => " ESCAPE '\\'"),
+      'NOT LIKE' => array('postfix' => " ESCAPE '\\'"),
+      'LIKE BINARY' => array('postfix' => " ESCAPE '\\'", 'operator' => 'GLOB'),
+      'NOT LIKE BINARY' => array('postfix' => " ESCAPE '\\'", 'operator' => 'NOT GLOB'),
+    );
+    return isset($specials[$operator]) ? $specials[$operator] : NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareQuery($query) {
+    return $this->prepare($this->prefixTables($query));
+  }
+
+  public function nextId($existing_id = 0) {
+    $this->startTransaction();
+    // We can safely use literal queries here instead of the slower query
+    // builder because if a given database breaks here then it can simply
+    // override nextId. However, this is unlikely as we deal with short strings
+    // and integers and no known databases require special handling for those
+    // simple cases. If another transaction wants to write the same row, it will
+    // wait until this transaction commits. Also, the return value needs to be
+    // set to RETURN_AFFECTED as if it were a real update() query otherwise it
+    // is not possible to get the row count properly.
+    $affected = $this->query('UPDATE {sequences} SET value = GREATEST(value, :existing_id) + 1', array(
+      ':existing_id' => $existing_id,
+    ), array('return' => Database::RETURN_AFFECTED));
+    if (!$affected) {
+      $this->query('INSERT INTO {sequences} (value) VALUES (:existing_id + 1)', array(
+        ':existing_id' => $existing_id,
+      ));
+    }
+    // The transaction gets committed when the transaction object gets destroyed
+    // because it gets out of scope.
+    return $this->query('SELECT value FROM {sequences}')->fetchField();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFullQualifiedTableName($table) {
+    $prefix = $this->tablePrefix($table);
+
+    // Don't include the SQLite database file name as part of the table name.
+    return $prefix . $table;
+  }
+
+}
diff --git a/core/drivers/sqlite/src/Delete.php b/core/drivers/sqlite/src/Delete.php
new file mode 100644
index 0000000..1e90a36
--- /dev/null
+++ b/core/drivers/sqlite/src/Delete.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Delete.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Delete.
+=======
+ * Contains Drupal\sqlite\Delete
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Delete.php
+ */
+
+namespace Drupal\sqlite;
+
+use Drupal\Core\Database\Query\Delete as QueryDelete;
+
+/**
+ * SQLite specific implementation of \Drupal\Core\Database\Query\Delete.
+ */
+class Delete extends QueryDelete { }
diff --git a/core/drivers/sqlite/src/Insert.php b/core/drivers/sqlite/src/Insert.php
new file mode 100644
index 0000000..8553946
--- /dev/null
+++ b/core/drivers/sqlite/src/Insert.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Insert.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Insert.
+=======
+ * Contains Drupal\sqlite\Insert
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Insert.php
+ */
+
+namespace Drupal\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) || !empty($this->fromQuery)) {
+      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();
+    if (!empty($this->insertFields)) {
+      $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)) {
+      $insert_fields_string = $this->insertFields ? ' (' . implode(', ', $this->insertFields) . ') ' : ' ';
+      return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery;
+    }
+
+    return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') VALUES (' . implode(', ', $placeholders) . ')';
+  }
+
+}
diff --git a/core/drivers/sqlite/src/Install/Tasks.php b/core/drivers/sqlite/src/Install/Tasks.php
new file mode 100644
index 0000000..30d555f
--- /dev/null
+++ b/core/drivers/sqlite/src/Install/Tasks.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Install\Tasks.
+=======
+ * Contains Drupal\sqlite\Install\Tasks
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Install/Tasks.php
+ */
+
+namespace Drupal\sqlite\Install;
+
+use Drupal\Core\Database\Database;
+use Drupal\sqlite\Connection;
+use Drupal\Core\Database\DatabaseNotFoundException;
+use Drupal\Core\Database\Install\Tasks as InstallTasks;
+
+/**
+ * Specifies installation tasks for SQLite databases.
+ */
+class Tasks extends InstallTasks {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $pdoDriver = 'sqlite';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function name() {
+    return t('SQLite');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function minimumVersion() {
+    return '3.6.8';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormOptions(array $database) {
+    $form = parent::getFormOptions($database);
+
+    // Remove the options that only apply to client/server style databases.
+    unset($form['username'], $form['password'], $form['advanced_options']['host'], $form['advanced_options']['port']);
+
+    // Make the text more accurate for SQLite.
+    $form['database']['#title'] = t('Database file');
+    $form['database']['#description'] = t('The absolute path to the file where @drupal data will be stored. This must be writable by the web server and should exist outside of the web root.', array('@drupal' => drupal_install_profile_distribution_name()));
+    $default_database = \Drupal::service('site.path') . '/files/.ht.sqlite';
+    $form['database']['#default_value'] = empty($database['database']) ? $default_database : $database['database'];
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  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) {
+      // Attempt to create the database if it is not found.
+      if ($e->getCode() == Connection::DATABASE_NOT_FOUND) {
+        // Remove the database string from connection info.
+        $connection_info = Database::getConnectionInfo();
+        $database = $connection_info['default']['database'];
+
+        // We cannot use file_directory_temp() here because we haven't yet
+        // successfully connected to the database.
+        $connection_info['default']['database'] = drupal_tempnam(sys_get_temp_dir(), 'sqlite');
+
+        // In order to change the Database::$databaseInfo array, need to remove
+        // the active connection, then re-add it with the new info.
+        Database::removeConnection('default');
+        Database::addConnectionInfo('default', 'default', $connection_info['default']);
+
+        try {
+          Database::getConnection()->createDatabase($database);
+          Database::closeConnection();
+
+          // Now, restore the database config.
+          Database::removeConnection('default');
+          $connection_info['default']['database'] = $database;
+          Database::addConnectionInfo('default', 'default', $connection_info['default']);
+
+          // Check the database connection.
+          Database::getConnection();
+          $this->pass('Drupal can CONNECT to the database ok.');
+        }
+        catch (DatabaseNotFoundException $e) {
+          // Still no dice; probably a permission issue. Raise the error to the
+          // installer.
+          $this->fail(t('Database %database not found. The server reports the following message when attempting to create the database: %error.', array('%database' => $database, '%error' => $e->getMessage())));
+        }
+      }
+      else {
+        // Database connection failed for some other reason than the database
+        // not existing.
+        $this->fail(t('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;
+  }
+}
diff --git a/core/drivers/sqlite/src/Merge.php b/core/drivers/sqlite/src/Merge.php
new file mode 100644
index 0000000..015fbd9
--- /dev/null
+++ b/core/drivers/sqlite/src/Merge.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Merge.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Merge.
+=======
+ * Contains Drupal\sqlite\Merge
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Merge.php
+ */
+
+namespace Drupal\sqlite;
+
+use Drupal\Core\Database\Query\Merge as QueryMerge;
+
+class Merge extends QueryMerge { }
diff --git a/core/drivers/sqlite/src/Schema.php b/core/drivers/sqlite/src/Schema.php
new file mode 100644
index 0000000..93db370
--- /dev/null
+++ b/core/drivers/sqlite/src/Schema.php
@@ -0,0 +1,730 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Schema.
+=======
+ * Contains Drupal\sqlite\Schema
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Schema.php
+ */
+
+namespace Drupal\sqlite;
+
+use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Database\SchemaObjectExistsException;
+use Drupal\Core\Database\SchemaObjectDoesNotExistException;
+use Drupal\Core\Database\Schema as DatabaseSchema;
+
+/**
+ * @ingroup schemaapi
+ * @{
+ */
+
+class Schema extends DatabaseSchema {
+
+  /**
+   * Override DatabaseSchema::$defaultSchema
+   */
+  protected $defaultSchema = 'main';
+
+  public function tableExists($table) {
+    $info = $this->getPrefixInfo($table);
+
+    // Don't use {} around sqlite_master table.
+    return (bool) $this->connection->query('SELECT 1 FROM ' . $info['schema'] . '.sqlite_master WHERE type = :type AND name = :name', array(':type' => 'table', ':name' => $info['table']))->fetchField();
+  }
+
+  public function fieldExists($table, $column) {
+    $schema = $this->introspectSchema($table);
+    return !empty($schema['fields'][$column]);
+  }
+
+  /**
+   * Generate SQL to create a new table from a Drupal schema definition.
+   *
+   * @param $name
+   *   The name of the table to create.
+   * @param $table
+   *   A Schema API table definition array.
+   * @return
+   *   An array of SQL statements to create the table.
+   */
+  public function createTableSql($name, $table) {
+    $sql = array();
+    $sql[] = "CREATE TABLE {" . $name . "} (\n" . $this->createColumnsSql($name, $table) . "\n);\n";
+    return array_merge($sql, $this->createIndexSql($name, $table));
+  }
+
+  /**
+   * Build the SQL expression for indexes.
+   */
+  protected function createIndexSql($tablename, $schema) {
+    $sql = array();
+    $info = $this->getPrefixInfo($tablename);
+    if (!empty($schema['unique keys'])) {
+      foreach ($schema['unique keys'] as $key => $fields) {
+        $sql[] = 'CREATE UNIQUE INDEX ' . $info['schema'] . '.' . $info['table'] . '_' . $key . ' ON ' . $info['table'] . ' (' . $this->createKeySql($fields) . "); \n";
+      }
+    }
+    if (!empty($schema['indexes'])) {
+      foreach ($schema['indexes'] as $key => $fields) {
+        $sql[] = 'CREATE INDEX ' . $info['schema'] . '.' . $info['table'] . '_' . $key . ' ON ' . $info['table'] . ' (' . $this->createKeySql($fields) . "); \n";
+      }
+    }
+    return $sql;
+  }
+
+  /**
+   * Build the SQL expression for creating columns.
+   */
+  protected function createColumnsSql($tablename, $schema) {
+    $sql_array = array();
+
+    // Add the SQL statement for each field.
+    foreach ($schema['fields'] as $name => $field) {
+      if (isset($field['type']) && $field['type'] == 'serial') {
+        if (isset($schema['primary key']) && ($key = array_search($name, $schema['primary key'])) !== FALSE) {
+          unset($schema['primary key'][$key]);
+        }
+      }
+      $sql_array[] = $this->createFieldSql($name, $this->processField($field));
+    }
+
+    // Process keys.
+    if (!empty($schema['primary key'])) {
+      $sql_array[] = " PRIMARY KEY (" . $this->createKeySql($schema['primary key']) . ")";
+    }
+
+    return implode(", \n", $sql_array);
+  }
+
+  /**
+   * Build the SQL expression for keys.
+   */
+  protected function createKeySql($fields) {
+    $return = array();
+    foreach ($fields as $field) {
+      if (is_array($field)) {
+        $return[] = $field[0];
+      }
+      else {
+        $return[] = $field;
+      }
+    }
+    return implode(', ', $return);
+  }
+
+  /**
+   * Set database-engine specific properties for a field.
+   *
+   * @param $field
+   *   A field description array, as specified in the schema documentation.
+   */
+  protected function processField($field) {
+    if (!isset($field['size'])) {
+      $field['size'] = 'normal';
+    }
+
+    // Set the correct database-engine specific datatype.
+    // In case one is already provided, force it to uppercase.
+    if (isset($field['sqlite_type'])) {
+      $field['sqlite_type'] = Unicode::strtoupper($field['sqlite_type']);
+    }
+    else {
+      $map = $this->getFieldTypeMap();
+      $field['sqlite_type'] = $map[$field['type'] . ':' . $field['size']];
+
+      // Numeric fields with a specified scale have to be stored as floats.
+      if ($field['sqlite_type'] === 'NUMERIC' && isset($field['scale'])) {
+        $field['sqlite_type'] = 'FLOAT';
+      }
+    }
+
+    if (isset($field['type']) && $field['type'] == 'serial') {
+      $field['auto_increment'] = TRUE;
+    }
+
+    return $field;
+  }
+
+  /**
+   * Create an SQL string for a field to be used in table creation or alteration.
+   *
+   * Before passing a field out of a schema definition into this function it has
+   * to be processed by db_processField().
+   *
+   * @param $name
+   *    Name of the field.
+   * @param $spec
+   *    The field specification, as per the schema data structure format.
+   */
+  protected function createFieldSql($name, $spec) {
+    if (!empty($spec['auto_increment'])) {
+      $sql = $name . " INTEGER PRIMARY KEY AUTOINCREMENT";
+      if (!empty($spec['unsigned'])) {
+        $sql .= ' CHECK (' . $name . '>= 0)';
+      }
+    }
+    else {
+      $sql = $name . ' ' . $spec['sqlite_type'];
+
+      if (in_array($spec['sqlite_type'], array('VARCHAR', 'TEXT'))) {
+        if (isset($spec['length'])) {
+          $sql .= '(' . $spec['length'] . ')';
+        }
+
+        if (isset($spec['binary']) && $spec['binary'] === FALSE) {
+          $sql .= ' COLLATE NOCASE_UTF8';
+        }
+      }
+
+      if (isset($spec['not null'])) {
+        if ($spec['not null']) {
+          $sql .= ' NOT NULL';
+        }
+        else {
+          $sql .= ' NULL';
+        }
+      }
+
+      if (!empty($spec['unsigned'])) {
+        $sql .= ' CHECK (' . $name . '>= 0)';
+      }
+
+      if (isset($spec['default'])) {
+        if (is_string($spec['default'])) {
+          $spec['default'] = $this->connection->quote($spec['default']);
+        }
+        $sql .= ' DEFAULT ' . $spec['default'];
+      }
+
+      if (empty($spec['not null']) && !isset($spec['default'])) {
+        $sql .= ' DEFAULT NULL';
+      }
+    }
+    return $sql;
+  }
+
+  /**
+   * This maps a generic data type in combination with its data size
+   * to the engine-specific data type.
+   */
+  public function getFieldTypeMap() {
+    // Put :normal last so it gets preserved by array_flip. This makes
+    // it much easier for modules (such as schema.module) to map
+    // database types back into schema types.
+    // $map does not use drupal_static as its value never changes.
+    static $map = array(
+      'varchar_ascii:normal' => 'VARCHAR',
+
+      'varchar:normal'  => 'VARCHAR',
+      'char:normal'     => 'CHAR',
+
+      'text:tiny'       => 'TEXT',
+      'text:small'      => 'TEXT',
+      'text:medium'     => 'TEXT',
+      'text:big'        => 'TEXT',
+      'text:normal'     => 'TEXT',
+
+      'serial:tiny'     => 'INTEGER',
+      'serial:small'    => 'INTEGER',
+      'serial:medium'   => 'INTEGER',
+      'serial:big'      => 'INTEGER',
+      'serial:normal'   => 'INTEGER',
+
+      'int:tiny'        => 'INTEGER',
+      'int:small'       => 'INTEGER',
+      'int:medium'      => 'INTEGER',
+      'int:big'         => 'INTEGER',
+      'int:normal'      => 'INTEGER',
+
+      'float:tiny'      => 'FLOAT',
+      'float:small'     => 'FLOAT',
+      'float:medium'    => 'FLOAT',
+      'float:big'       => 'FLOAT',
+      'float:normal'    => 'FLOAT',
+
+      'numeric:normal'  => 'NUMERIC',
+
+      'blob:big'        => 'BLOB',
+      'blob:normal'     => 'BLOB',
+    );
+    return $map;
+  }
+
+  public function renameTable($table, $new_name) {
+    if (!$this->tableExists($table)) {
+      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 SchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
+    }
+
+    $schema = $this->introspectSchema($table);
+
+    // SQLite doesn't allow you to rename tables outside of the current
+    // database. So the syntax '... RENAME TO database.table' would fail.
+    // So we must determine the full table name here rather than surrounding
+    // the table with curly braces in case the db_prefix contains a reference
+    // to a database outside of our existing database.
+    $info = $this->getPrefixInfo($new_name);
+    $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO ' . $info['table']);
+
+    // Drop the indexes, there is no RENAME INDEX command in SQLite.
+    if (!empty($schema['unique keys'])) {
+      foreach ($schema['unique keys'] as $key => $fields) {
+        $this->dropIndex($table, $key);
+      }
+    }
+    if (!empty($schema['indexes'])) {
+      foreach ($schema['indexes'] as $index => $fields) {
+        $this->dropIndex($table, $index);
+      }
+    }
+
+    // Recreate the indexes.
+    $statements = $this->createIndexSql($new_name, $schema);
+    foreach ($statements as $statement) {
+      $this->connection->query($statement);
+    }
+  }
+
+  public function dropTable($table) {
+    if (!$this->tableExists($table)) {
+      return FALSE;
+    }
+    $this->connection->tableDropped = TRUE;
+    $this->connection->query('DROP TABLE {' . $table . '}');
+    return TRUE;
+  }
+
+  public function addField($table, $field, $specification, $keys_new = array()) {
+    if (!$this->tableExists($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 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
+    // supports adding new fields to a table, in some simple cases. In most
+    // cases, we have to create a new table and copy the data over.
+    if (empty($keys_new) && (empty($specification['not null']) || isset($specification['default']))) {
+      // When we don't have to create new keys and we are not creating a
+      // NOT NULL column without a default value, we can use the quicker version.
+      $query = 'ALTER TABLE {' . $table . '} ADD ' . $this->createFieldSql($field, $this->processField($specification));
+      $this->connection->query($query);
+
+      // Apply the initial value if set.
+      if (isset($specification['initial'])) {
+        $this->connection->update($table)
+          ->fields(array($field => $specification['initial']))
+          ->execute();
+      }
+    }
+    else {
+      // We cannot add the field directly. Use the slower table alteration
+      // method, starting from the old schema.
+      $old_schema = $this->introspectSchema($table);
+      $new_schema = $old_schema;
+
+      // Add the new field.
+      $new_schema['fields'][$field] = $specification;
+
+      // Build the mapping between the old fields and the new fields.
+      $mapping = array();
+      if (isset($specification['initial'])) {
+        // If we have a initial value, copy it over.
+        $mapping[$field] = array(
+          'expression' => ':newfieldinitial',
+          'arguments' => array(':newfieldinitial' => $specification['initial']),
+        );
+      }
+      else {
+        // Else use the default of the field.
+        $mapping[$field] = NULL;
+      }
+
+      // Add the new indexes.
+      $new_schema += $keys_new;
+
+      $this->alterTable($table, $old_schema, $new_schema, $mapping);
+    }
+  }
+
+  /**
+   * Create a table with a new schema containing the old content.
+   *
+   * As SQLite does not support ALTER TABLE (with a few exceptions) it is
+   * necessary to create a new table and copy over the old content.
+   *
+   * @param $table
+   *   Name of the table to be altered.
+   * @param $old_schema
+   *   The old schema array for the table.
+   * @param $new_schema
+   *   The new schema array for the table.
+   * @param $mapping
+   *   An optional mapping between the fields of the old specification and the
+   *   fields of the new specification. An associative array, whose keys are
+   *   the fields of the new table, and values can take two possible forms:
+   *     - a simple string, which is interpreted as the name of a field of the
+   *       old table,
+   *     - an associative array with two keys 'expression' and 'arguments',
+   *       that will be used as an expression field.
+   */
+  protected function alterTable($table, $old_schema, $new_schema, array $mapping = array()) {
+    $i = 0;
+    do {
+      $new_table = $table . '_' . $i++;
+    } while ($this->tableExists($new_table));
+
+    $this->createTable($new_table, $new_schema);
+
+    // Build a SQL query to migrate the data from the old table to the new.
+    $select = $this->connection->select($table);
+
+    // Complete the mapping.
+    $possible_keys = array_keys($new_schema['fields']);
+    $mapping += array_combine($possible_keys, $possible_keys);
+
+    // Now add the fields.
+    foreach ($mapping as $field_alias => $field_source) {
+      // Just ignore this field (ie. use it's default value).
+      if (!isset($field_source)) {
+        continue;
+      }
+
+      if (is_array($field_source)) {
+        $select->addExpression($field_source['expression'], $field_alias, $field_source['arguments']);
+      }
+      else {
+        $select->addField($table, $field_source, $field_alias);
+      }
+    }
+
+    // Execute the data migration query.
+    $this->connection->insert($new_table)
+      ->from($select)
+      ->execute();
+
+    $old_count = $this->connection->query('SELECT COUNT(*) FROM {' . $table . '}')->fetchField();
+    $new_count = $this->connection->query('SELECT COUNT(*) FROM {' . $new_table . '}')->fetchField();
+    if ($old_count == $new_count) {
+      $this->dropTable($table);
+      $this->renameTable($new_table, $table);
+    }
+  }
+
+  /**
+   * Find out the schema of a table.
+   *
+   * This function uses introspection methods provided by the database to
+   * create a schema array. This is useful, for example, during update when
+   * the old schema is not available.
+   *
+   * @param $table
+   *   Name of the table.
+   * @return
+   *   An array representing the schema, from drupal_get_schema().
+   */
+  protected function introspectSchema($table) {
+    $mapped_fields = array_flip($this->getFieldTypeMap());
+    $schema = array(
+      'fields' => array(),
+      'primary key' => array(),
+      'unique keys' => array(),
+      'indexes' => array(),
+    );
+
+    $info = $this->getPrefixInfo($table);
+    $result = $this->connection->query('PRAGMA ' . $info['schema'] . '.table_info(' . $info['table'] . ')');
+    foreach ($result as $row) {
+      if (preg_match('/^([^(]+)\((.*)\)$/', $row->type, $matches)) {
+        $type = $matches[1];
+        $length = $matches[2];
+      }
+      else {
+        $type = $row->type;
+        $length = NULL;
+      }
+      if (isset($mapped_fields[$type])) {
+        list($type, $size) = explode(':', $mapped_fields[$type]);
+        $schema['fields'][$row->name] = array(
+          'type' => $type,
+          'size' => $size,
+          'not null' => !empty($row->notnull),
+          'default' => trim($row->dflt_value, "'"),
+        );
+        if ($length) {
+          $schema['fields'][$row->name]['length'] = $length;
+        }
+        if ($row->pk) {
+          $schema['primary key'][] = $row->name;
+        }
+      }
+      else {
+        new \Exception("Unable to parse the column type " . $row->type);
+      }
+    }
+    $indexes = array();
+    $result = $this->connection->query('PRAGMA ' . $info['schema'] . '.index_list(' . $info['table'] . ')');
+    foreach ($result as $row) {
+      if (strpos($row->name, 'sqlite_autoindex_') !== 0) {
+        $indexes[] = array(
+          'schema_key' => $row->unique ? 'unique keys' : 'indexes',
+          'name' => $row->name,
+        );
+      }
+    }
+    foreach ($indexes as $index) {
+      $name = $index['name'];
+      // Get index name without prefix.
+      $index_name = substr($name, strlen($info['table']) + 1);
+      $result = $this->connection->query('PRAGMA ' . $info['schema'] . '.index_info(' . $name . ')');
+      foreach ($result as $row) {
+        $schema[$index['schema_key']][$index_name][] = $row->name;
+      }
+    }
+    return $schema;
+  }
+
+  public function dropField($table, $field) {
+    if (!$this->fieldExists($table, $field)) {
+      return FALSE;
+    }
+
+    $old_schema = $this->introspectSchema($table);
+    $new_schema = $old_schema;
+
+    unset($new_schema['fields'][$field]);
+
+    // Handle possible primary key changes.
+    if (isset($new_schema['primary key']) && ($key = array_search($field, $new_schema['primary key'])) !== FALSE) {
+      unset($new_schema['primary key'][$key]);
+    }
+
+    // Handle possible index changes.
+    foreach ($new_schema['indexes'] as $index => $fields) {
+      foreach ($fields as $key => $field_name) {
+        if ($field_name == $field) {
+          unset($new_schema['indexes'][$index][$key]);
+        }
+      }
+      // If this index has no more fields then remove it.
+      if (empty($new_schema['indexes'][$index])) {
+        unset($new_schema['indexes'][$index]);
+      }
+    }
+    $this->alterTable($table, $old_schema, $new_schema);
+    return TRUE;
+  }
+
+  public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
+    if (!$this->fieldExists($table, $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 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);
+    $new_schema = $old_schema;
+
+    // Map the old field to the new field.
+    if ($field != $field_new) {
+      $mapping[$field_new] = $field;
+    }
+    else {
+      $mapping = array();
+    }
+
+    // Remove the previous definition and swap in the new one.
+    unset($new_schema['fields'][$field]);
+    $new_schema['fields'][$field_new] = $spec;
+
+    // Map the former indexes to the new column name.
+    $new_schema['primary key'] = $this->mapKeyDefinition($new_schema['primary key'], $mapping);
+    foreach (array('unique keys', 'indexes') as $k) {
+      foreach ($new_schema[$k] as &$key_definition) {
+        $key_definition = $this->mapKeyDefinition($key_definition, $mapping);
+      }
+    }
+
+    // Add in the keys from $keys_new.
+    if (isset($keys_new['primary key'])) {
+      $new_schema['primary key'] = $keys_new['primary key'];
+    }
+    foreach (array('unique keys', 'indexes') as $k) {
+      if (!empty($keys_new[$k])) {
+        $new_schema[$k] = $keys_new[$k] + $new_schema[$k];
+      }
+    }
+
+    $this->alterTable($table, $old_schema, $new_schema, $mapping);
+  }
+
+  /**
+   * Utility method: rename columns in an index definition according to a new mapping.
+   *
+   * @param $key_definition
+   *   The key definition.
+   * @param $mapping
+   *   The new mapping.
+   */
+  protected function mapKeyDefinition(array $key_definition, array $mapping) {
+    foreach ($key_definition as &$field) {
+      // The key definition can be an array($field, $length).
+      if (is_array($field)) {
+        $field = &$field[0];
+      }
+      if (isset($mapping[$field])) {
+        $field = $mapping[$field];
+      }
+    }
+    return $key_definition;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addIndex($table, $name, $fields, array $spec) {
+    if (!$this->tableExists($table)) {
+      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 SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
+    }
+
+    $schema['indexes'][$name] = $fields;
+    $statements = $this->createIndexSql($table, $schema);
+    foreach ($statements as $statement) {
+      $this->connection->query($statement);
+    }
+  }
+
+  public function indexExists($table, $name) {
+    $info = $this->getPrefixInfo($table);
+
+    return $this->connection->query('PRAGMA ' . $info['schema'] . '.index_info(' . $info['table'] . '_' . $name . ')')->fetchField() != '';
+  }
+
+  public function dropIndex($table, $name) {
+    if (!$this->indexExists($table, $name)) {
+      return FALSE;
+    }
+
+    $info = $this->getPrefixInfo($table);
+
+    $this->connection->query('DROP INDEX ' . $info['schema'] . '.' . $info['table'] . '_' . $name);
+    return TRUE;
+  }
+
+  public function addUniqueKey($table, $name, $fields) {
+    if (!$this->tableExists($table)) {
+      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 SchemaObjectExistsException(t("Cannot add unique key @name to table @table: unique key already exists.", array('@table' => $table, '@name' => $name)));
+    }
+
+    $schema['unique keys'][$name] = $fields;
+    $statements = $this->createIndexSql($table, $schema);
+    foreach ($statements as $statement) {
+      $this->connection->query($statement);
+    }
+  }
+
+  public function dropUniqueKey($table, $name) {
+    if (!$this->indexExists($table, $name)) {
+      return FALSE;
+    }
+
+    $info = $this->getPrefixInfo($table);
+
+    $this->connection->query('DROP INDEX ' . $info['schema'] . '.' . $info['table'] . '_' . $name);
+    return TRUE;
+  }
+
+  public function addPrimaryKey($table, $fields) {
+    if (!$this->tableExists($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 SchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
+    }
+
+    $new_schema['primary key'] = $fields;
+    $this->alterTable($table, $old_schema, $new_schema);
+  }
+
+  public function dropPrimaryKey($table) {
+    $old_schema = $this->introspectSchema($table);
+    $new_schema = $old_schema;
+
+    if (empty($new_schema['primary key'])) {
+      return FALSE;
+    }
+
+    unset($new_schema['primary key']);
+    $this->alterTable($table, $old_schema, $new_schema);
+    return TRUE;
+  }
+
+  public function fieldSetDefault($table, $field, $default) {
+    if (!$this->fieldExists($table, $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);
+    $new_schema = $old_schema;
+
+    $new_schema['fields'][$field]['default'] = $default;
+    $this->alterTable($table, $old_schema, $new_schema);
+  }
+
+  public function fieldSetNoDefault($table, $field) {
+    if (!$this->fieldExists($table, $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);
+    $new_schema = $old_schema;
+
+    unset($new_schema['fields'][$field]['default']);
+    $this->alterTable($table, $old_schema, $new_schema);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function findTables($table_expression) {
+    $tables = [];
+
+    // The SQLite implementation doesn't need to use the same filtering strategy
+    // as the parent one because individually prefixed tables live in their own
+    // schema (database), which means that neither the main database nor any
+    // attached one will contain a prefixed table name, so we just need to loop
+    // over all known schemas and filter by the user-supplied table expression.
+    $attached_dbs = $this->connection->getAttachedDatabases();
+    foreach ($attached_dbs as $schema) {
+      // Can't use query placeholders for the schema because the query would
+      // have to be :prefixsqlite_master, which does not work. We also need to
+      // ignore the internal SQLite tables.
+      $result = db_query("SELECT name FROM " . $schema . ".sqlite_master WHERE type = :type AND name LIKE :table_name AND name NOT LIKE :pattern", array(
+        ':type' => 'table',
+        ':table_name' => $table_expression,
+        ':pattern' => 'sqlite_%',
+      ));
+      $tables += $result->fetchAllKeyed(0, 0);
+    }
+
+    return $tables;
+  }
+
+}
diff --git a/core/drivers/sqlite/src/Select.php b/core/drivers/sqlite/src/Select.php
new file mode 100644
index 0000000..2f5cdc7
--- /dev/null
+++ b/core/drivers/sqlite/src/Select.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Select.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Select.
+=======
+ * Contains Drupal\sqlite\Select
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Select.php
+ */
+
+namespace Drupal\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/drivers/sqlite/src/Statement.php b/core/drivers/sqlite/src/Statement.php
new file mode 100644
index 0000000..8207182
--- /dev/null
+++ b/core/drivers/sqlite/src/Statement.php
@@ -0,0 +1,153 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Statement.
+=======
+ * Contains Drupal\sqlite\Statement
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Statement.php
+ */
+
+namespace Drupal\sqlite;
+
+use Drupal\Core\Database\StatementPrefetch;
+use Drupal\Core\Database\StatementInterface;
+
+/**
+ * Specific SQLite implementation of DatabaseConnection.
+ *
+ * The PDO SQLite driver only closes SELECT statements when the PDOStatement
+ * destructor is called and SQLite does not allow data change (INSERT,
+ * UPDATE etc) on a table which has open SELECT statements. This is a
+ * user-space mock of PDOStatement that buffers all the data and doesn't
+ * have those limitations.
+ */
+class Statement extends StatementPrefetch implements StatementInterface {
+
+  /**
+   * {@inheritdoc}
+   *
+   * 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->pdoConnection->prepare($query);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  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/drivers/sqlite/src/Transaction.php b/core/drivers/sqlite/src/Transaction.php
new file mode 100644
index 0000000..891a922
--- /dev/null
+++ b/core/drivers/sqlite/src/Transaction.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Transaction.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Transaction.
+=======
+ * Contains Drupal\sqlite\Transaction
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Transaction.php
+ */
+
+namespace Drupal\sqlite;
+
+use Drupal\Core\Database\Transaction as DatabaseTransaction;
+
+class Transaction extends DatabaseTransaction { }
diff --git a/core/drivers/sqlite/src/Truncate.php b/core/drivers/sqlite/src/Truncate.php
new file mode 100644
index 0000000..304e9b2
--- /dev/null
+++ b/core/drivers/sqlite/src/Truncate.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Truncate.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Truncate.
+=======
+ * Contains Drupal\sqlite\Truncate
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Truncate.php
+ */
+
+namespace Drupal\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) . '} ';
+  }
+}
diff --git a/core/drivers/sqlite/src/Update.php b/core/drivers/sqlite/src/Update.php
new file mode 100644
index 0000000..a7a6e6d
--- /dev/null
+++ b/core/drivers/sqlite/src/Update.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+<<<<<<< HEAD:core/lib/Drupal/Core/Database/Driver/sqlite/Update.php
+ * Contains \Drupal\Core\Database\Driver\sqlite\Update.
+=======
+ * Contains Drupal\sqlite\Update
+>>>>>>> Applying patch from issue 2209307 comment 34:core/drivers/sqlite/src/Update.php
+ */
+
+namespace Drupal\sqlite;
+
+use Drupal\Core\Database\Query\Update as QueryUpdate;
+
+class Update extends QueryUpdate { }
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index b25d28c..cb0566c 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -341,6 +341,7 @@ function install_begin_request($class_loader, &$install_state) {
   // used or output for these calls.
   // @todo Separate API level checks from UI-facing error messages.
   $container = new ContainerBuilder();
+  $container->set('class_loader', $class_loader);
   $container->setParameter('language.default_values', Language::$defaultValues);
   $container
     ->register('language.default', 'Drupal\Core\Language\LanguageDefault')
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 42b0d40..83a57b1 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -135,23 +135,15 @@ function drupal_detect_database_types() {
  */
 function drupal_get_database_types() {
   $databases = array();
-  $drivers = array();
+  $discovery = new ExtensionDiscovery();
+  $discovery->setProfileDirectories(array());
 
-  // The internal database driver name is any valid PHP identifier.
-  $mask = '/^' . DRUPAL_PHP_FUNCTION_PATTERN . '$/';
-  $files = file_scan_directory(DRUPAL_ROOT . '/core/lib/Drupal/Core/Database/Driver', $mask, array('recurse' => FALSE));
-  if (is_dir(DRUPAL_ROOT . '/drivers/lib/Drupal/Driver/Database')) {
-    $files += file_scan_directory(DRUPAL_ROOT . '/drivers/lib/Drupal/Driver/Database/', $mask, array('recurse' => FALSE));
-  }
-  foreach ($files as $file) {
-    if (file_exists($file->uri . '/Install/Tasks.php')) {
-      $drivers[$file->filename] = $file->uri;
-    }
-  }
-  foreach ($drivers as $driver => $file) {
-    $installer = db_installer_object($driver);
+  foreach ($discovery->scan('driver') as $driver_name => $driver) {
+    drupal_classloader_register($driver_name, $driver->getPath());
+
+    $installer = db_installer_object($driver_name);
     if ($installer->installable()) {
-      $databases[$driver] = $installer;
+      $databases[$driver_name] = $installer;
     }
   }
 
@@ -1063,12 +1055,6 @@ function install_profile_info($profile, $langcode = 'en') {
 function db_installer_object($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";
-  if (class_exists($task_class)) {
-    return new $task_class();
-  }
-  else {
-    $task_class = "Drupal\\Driver\\Database\\{$driver}\\Install\\Tasks";
-    return new $task_class();
-  }
+  $task_class = "Drupal\\{$driver}\\Install\\Tasks";
+  return new $task_class();
 }
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index b1a911a..80d78f5 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -20,7 +20,12 @@
 use Drupal\Core\Theme\ThemeSettings;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Render\Element;
+<<<<<<< HEAD
 use Drupal\Core\Render\SafeString;
+=======
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\Exception\RouteNotFoundException;
+>>>>>>> Applying patch from issue 2209307 comment 34
 
 /**
  * @defgroup content_flags Content markers
@@ -1300,7 +1305,14 @@ function template_preprocess_page(&$variables) {
   }
 
   $variables['base_path']         = base_path();
-  $variables['front_page']        = \Drupal::url('<front>');
+  // This may be called in the early installer.
+  // @todo Fix this properly in some way.
+  try {
+    $variables['front_page']      = \Drupal::url('<front>');
+  }
+  catch (RouteNotFoundException $e) {
+    $variables['front_page']      = '';
+  }
   $variables['language']          = $language_interface;
 
   // An exception might be thrown.
diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php
index 18283ce..f4c80c3 100644
--- a/core/lib/Drupal/Core/Database/Connection.php
+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -741,13 +741,7 @@ protected function expandArguments(&$query, &$args) {
   public function getDriverClass($class) {
     if (empty($this->driverClasses[$class])) {
       $driver = $this->driver();
-      if (!empty($this->connectionOptions['namespace'])) {
-        $driver_class  = $this->connectionOptions['namespace'] . '\\' . $class;
-      }
-      else {
-        // Fallback for Drupal 7 settings.php.
-        $driver_class = "Drupal\\Core\\Database\\Driver\\{$driver}\\{$class}";
-      }
+      $driver_class = "Drupal\\{$driver}\\{$class}";
       $this->driverClasses[$class] = class_exists($driver_class) ? $driver_class : $class;
     }
     return $this->driverClasses[$class];
diff --git a/core/lib/Drupal/Core/Database/Database.php b/core/lib/Drupal/Core/Database/Database.php
index d48c6f2..f1e6fc3 100644
--- a/core/lib/Drupal/Core/Database/Database.php
+++ b/core/lib/Drupal/Core/Database/Database.php
@@ -255,7 +255,13 @@
    */
   final public static function addConnectionInfo($key, $target, array $info) {
     if (empty(self::$databaseInfo[$key][$target])) {
-      self::$databaseInfo[$key][$target] = self::parseConnectionInfo($info);
+      $info = self::parseConnectionInfo($info);
+      self::$databaseInfo[$key][$target] = $info;
+
+      // @todo Hard-wired dependency on Composer's ClassLoader.
+      \ComposerAutoloaderInitDrupal8::getLoader()
+        // Ensure to set (replace), not add (cumulative) for each connection.
+        ->setPsr4('Drupal\\' . $info['driver'] . '\\', $info['path']);
     }
   }
 
@@ -370,13 +376,7 @@
       throw new DriverNotSpecifiedException('Driver not specified for this database connection: ' . $key);
     }
 
-    if (!empty(self::$databaseInfo[$key][$target]['namespace'])) {
-      $driver_class = self::$databaseInfo[$key][$target]['namespace'] . '\\Connection';
-    }
-    else {
-      // Fallback for Drupal 7 settings.php.
-      $driver_class = "Drupal\\Core\\Database\\Driver\\{$driver}\\Connection";
-    }
+    $driver_class = "Drupal\\$driver\\Connection";
 
     $pdo_connection = $driver_class::open(self::$databaseInfo[$key][$target]);
     $new_connection = new $driver_class($pdo_connection, self::$databaseInfo[$key][$target]);
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
deleted file mode 100644
index c48c275..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
+++ /dev/null
@@ -1,328 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\mysql\Connection.
- */
-
-namespace Drupal\Core\Database\Driver\mysql;
-
-use Drupal\Core\Database\DatabaseExceptionWrapper;
-
-use Drupal\Core\Database\Database;
-use Drupal\Core\Database\DatabaseNotFoundException;
-use Drupal\Core\Database\TransactionCommitFailedException;
-use Drupal\Core\Database\DatabaseException;
-use Drupal\Core\Database\Connection as DatabaseConnection;
-use Drupal\Component\Utility\Unicode;
-
-/**
- * @addtogroup database
- * @{
- */
-
-class Connection extends DatabaseConnection {
-
-  /**
-   * Error code for "Unknown database" error.
-   */
-  const DATABASE_NOT_FOUND = 1049;
-
-  /**
-   * Error code for "Can't initialize character set" error.
-   */
-  const UNSUPPORTED_CHARSET = 2019;
-
-  /**
-   * Flag to indicate if the cleanup function in __destruct() should run.
-   *
-   * @var bool
-   */
-  protected $needsCleanup = FALSE;
-
-  /**
-   * The minimal possible value for the max_allowed_packet setting of MySQL.
-   *
-   * @link https://mariadb.com/kb/en/mariadb/server-system-variables/#max_allowed_packet
-   * @link https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_allowed_packet
-   *
-   * @var int
-   */
-  const MIN_MAX_ALLOWED_PACKET = 1024;
-
-  /**
-   * Constructs a Connection object.
-   */
-  public function __construct(\PDO $connection, array $connection_options = array()) {
-    parent::__construct($connection, $connection_options);
-
-    // This driver defaults to transaction support, except if explicitly passed FALSE.
-    $this->transactionSupport = !isset($connection_options['transactions']) || ($connection_options['transactions'] !== FALSE);
-
-    // MySQL never supports transactional DDL.
-    $this->transactionalDDLSupport = FALSE;
-
-    $this->connectionOptions = $connection_options;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function query($query, array $args = array(), $options = array()) {
-    try {
-      return parent::query($query, $args, $options);
-    } catch (DatabaseException $e) {
-      if ($e->getPrevious()->errorInfo[1] == 1153) {
-        // If a max_allowed_packet error occurs the message length is truncated.
-        // This should prevent the error from recurring if the exception is
-        // logged to the database using dblog or the like.
-        $message = Unicode::truncateBytes($e->getMessage(), self::MIN_MAX_ALLOWED_PACKET);
-        $e = new DatabaseExceptionWrapper($message, $e->getCode(), $e->getPrevious());
-      }
-      throw $e;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function open(array &$connection_options = array()) {
-    if (isset($connection_options['_dsn_utf8_fallback']) && $connection_options['_dsn_utf8_fallback'] === TRUE) {
-      // Only used during the installer version check, as a fallback from utf8mb4.
-      $charset = 'utf8';
-    }
-    else {
-      $charset = 'utf8mb4';
-    }
-    // The DSN should use either a socket or a host/port.
-    if (isset($connection_options['unix_socket'])) {
-      $dsn = 'mysql:unix_socket=' . $connection_options['unix_socket'];
-    }
-    else {
-      // Default to TCP connection on port 3306.
-      $dsn = 'mysql:host=' . $connection_options['host'] . ';port=' . (empty($connection_options['port']) ? 3306 : $connection_options['port']);
-    }
-    // Character set is added to dsn to ensure PDO uses the proper character
-    // set when escaping. This has security implications. See
-    // https://www.drupal.org/node/1201452 for further discussion.
-    $dsn .= ';charset=' . $charset;
-    if (!empty($connection_options['database'])) {
-      $dsn .= ';dbname=' . $connection_options['database'];
-    }
-    // Allow PDO options to be overridden.
-    $connection_options += array(
-      'pdo' => array(),
-    );
-    $connection_options['pdo'] += array(
-      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
-      // So we don't have to mess around with cursors and unbuffered queries by default.
-      \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
-      // Make sure MySQL returns all matched rows on update queries including
-      // rows that actually didn't have to be updated because the values didn't
-      // change. This matches common behavior among other database systems.
-      \PDO::MYSQL_ATTR_FOUND_ROWS => TRUE,
-      // Because MySQL's prepared statements skip the query cache, because it's dumb.
-      \PDO::ATTR_EMULATE_PREPARES => TRUE,
-    );
-    if (defined('\PDO::MYSQL_ATTR_MULTI_STATEMENTS')) {
-      // An added connection option in PHP 5.5.21 to optionally limit SQL to a
-      // single statement like mysqli.
-      $connection_options['pdo'] += [\PDO::MYSQL_ATTR_MULTI_STATEMENTS => FALSE];
-    }
-
-    $pdo = new \PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
-
-    // Force MySQL to use the UTF-8 character set. Also set the collation, if a
-    // certain one has been set; otherwise, MySQL defaults to
-    // 'utf8mb4_general_ci' for utf8mb4.
-    if (!empty($connection_options['collation'])) {
-      $pdo->exec('SET NAMES ' . $charset . ' COLLATE ' . $connection_options['collation']);
-    }
-    else {
-      $pdo->exec('SET NAMES ' . $charset);
-    }
-
-    // Set MySQL init_commands if not already defined.  Default Drupal's MySQL
-    // behavior to conform more closely to SQL standards.  This allows Drupal
-    // to run almost seamlessly on many different kinds of database systems.
-    // These settings force MySQL to behave the same as postgresql, or sqlite
-    // in regards to syntax interpretation and invalid data handling.  See
-    // https://www.drupal.org/node/344575 for further discussion. Also, as MySQL
-    // 5.5 changed the meaning of TRADITIONAL we need to spell out the modes one
-    // by one.
-    $connection_options += array(
-      'init_commands' => array(),
-    );
-    $connection_options['init_commands'] += array(
-      'sql_mode' => "SET sql_mode = 'ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,ONLY_FULL_GROUP_BY'",
-    );
-    // Execute initial commands.
-    foreach ($connection_options['init_commands'] as $sql) {
-      $pdo->exec($sql);
-    }
-
-    return $pdo;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function serialize() {
-    // Cleanup the connection, much like __destruct() does it as well.
-    if ($this->needsCleanup) {
-      $this->nextIdDelete();
-    }
-    $this->needsCleanup = FALSE;
-
-    return parent::serialize();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __destruct() {
-    if ($this->needsCleanup) {
-      $this->nextIdDelete();
-    }
-  }
-
-  public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
-    return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options);
-  }
-
-  public function queryTemporary($query, array $args = array(), array $options = array()) {
-    $tablename = $this->generateTemporaryTableName();
-    $this->query('CREATE TEMPORARY TABLE {' . $tablename . '} Engine=MEMORY ' . $query, $args, $options);
-    return $tablename;
-  }
-
-  public function driver() {
-    return 'mysql';
-  }
-
-  public function databaseType() {
-    return 'mysql';
-  }
-
-  /**
-   * Overrides \Drupal\Core\Database\Connection::createDatabase().
-   *
-   * @param string $database
-   *   The name of the database to create.
-   *
-   * @throws \Drupal\Core\Database\DatabaseNotFoundException
-   */
-  public function createDatabase($database) {
-    // Escape the database name.
-    $database = Database::getConnection()->escapeDatabase($database);
-
-    try {
-      // Create the database and set it as active.
-      $this->connection->exec("CREATE DATABASE $database");
-      $this->connection->exec("USE $database");
-    }
-    catch (\Exception $e) {
-      throw new DatabaseNotFoundException($e->getMessage());
-    }
-  }
-
-  public function mapConditionOperator($operator) {
-    // We don't want to override any of the defaults.
-    return NULL;
-  }
-
-  public function nextId($existing_id = 0) {
-    $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID));
-    // This should only happen after an import or similar event.
-    if ($existing_id >= $new_id) {
-      // If we INSERT a value manually into the sequences table, on the next
-      // INSERT, MySQL will generate a larger value. However, there is no way
-      // of knowing whether this value already exists in the table. MySQL
-      // provides an INSERT IGNORE which would work, but that can mask problems
-      // other than duplicate keys. Instead, we use INSERT ... ON DUPLICATE KEY
-      // UPDATE in such a way that the UPDATE does not do anything. This way,
-      // duplicate keys do not generate errors but everything else does.
-      $this->query('INSERT INTO {sequences} (value) VALUES (:value) ON DUPLICATE KEY UPDATE value = value', array(':value' => $existing_id));
-      $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID));
-    }
-    $this->needsCleanup = TRUE;
-    return $new_id;
-  }
-
-  public function nextIdDelete() {
-    // While we want to clean up the table to keep it up from occupying too
-    // much storage and memory, we must keep the highest value in the table
-    // because InnoDB uses an in-memory auto-increment counter as long as the
-    // server runs. When the server is stopped and restarted, InnoDB
-    // reinitializes the counter for each table for the first INSERT to the
-    // table based solely on values from the table so deleting all values would
-    // be a problem in this case. Also, TRUNCATE resets the auto increment
-    // counter.
-    try {
-      $max_id = $this->query('SELECT MAX(value) FROM {sequences}')->fetchField();
-      // We know we are using MySQL here, no need for the slower db_delete().
-      $this->query('DELETE FROM {sequences} WHERE value < :value', array(':value' => $max_id));
-    }
-    // During testing, this function is called from shutdown with the
-    // simpletest prefix stored in $this->connection, and those tables are gone
-    // by the time shutdown is called so we need to ignore the database
-    // errors. There is no problem with completely ignoring errors here: if
-    // these queries fail, the sequence will work just fine, just use a bit
-    // more database storage and memory.
-    catch (DatabaseException $e) {
-    }
-  }
-
-  /**
-   * Overridden to work around issues to MySQL not supporting transactional DDL.
-   */
-  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 (!$this->connection->commit()) {
-          throw new TransactionCommitFailedException();
-        }
-      }
-      else {
-        // Attempt to release this savepoint in the standard way.
-        try {
-          $this->query('RELEASE SAVEPOINT ' . $name);
-        }
-        catch (DatabaseExceptionWrapper $e) {
-          // However, in MySQL (InnoDB), savepoints are automatically committed
-          // when tables are altered or created (DDL transactions are not
-          // supported). This can cause exceptions due to trying to release
-          // savepoints which no longer exist.
-          //
-          // To avoid exceptions when no actual error has occurred, we silently
-          // succeed for MySQL error code 1305 ("SAVEPOINT does not exist").
-          if ($e->getPrevious()->errorInfo[1] == '1305') {
-            // If one SAVEPOINT was released automatically, then all were.
-            // Therefore, clean the transaction stack.
-            $this->transactionLayers = array();
-            // We also have to explain to PDO that the transaction stack has
-            // been cleaned-up.
-            $this->connection->commit();
-          }
-          else {
-            throw $e;
-          }
-        }
-      }
-    }
-  }
-
-}
-
-
-/**
- * @} End of "addtogroup database".
- */
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Delete.php b/core/lib/Drupal/Core/Database/Driver/mysql/Delete.php
deleted file mode 100644
index 4e594da..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Delete.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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/lib/Drupal/Core/Database/Driver/mysql/Insert.php b/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php
deleted file mode 100644
index b458d36..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\mysql\Insert.
- */
-
-namespace Drupal\Core\Database\Driver\mysql;
-
-use Drupal\Core\Database\Query\Insert as QueryInsert;
-
-class Insert extends QueryInsert {
-
-  public function execute() {
-    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)) {
-      $max_placeholder = 0;
-      $values = array();
-      foreach ($this->insertValues as $insert_values) {
-        foreach ($insert_values as $value) {
-          $values[':db_insert_placeholder_' . $max_placeholder++] = $value;
-        }
-      }
-    }
-    else {
-      $values = $this->fromQuery->getArguments();
-    }
-
-    $last_insert_id = $this->connection->query((string) $this, $values, $this->queryOptions);
-
-    // Re-initialize the values array so that we can re-use this query.
-    $this->insertValues = array();
-
-    return $last_insert_id;
-  }
-
-  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 we're selecting from a SelectQuery, finish building the query and
-    // pass it back, as any remaining options are irrelevant.
-    if (!empty($this->fromQuery)) {
-      $insert_fields_string = $insert_fields ? ' (' . implode(', ', $insert_fields) . ') ' : ' ';
-      return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery;
-    }
-
-    $query = $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
-
-    $values = $this->getInsertPlaceholderFragment($this->insertValues, $this->defaultFields);
-    $query .= implode(', ', $values);
-
-    return $query;
-  }
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php b/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php
deleted file mode 100644
index ee8bc1c..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php
+++ /dev/null
@@ -1,178 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\mysql\Install\Tasks.
- */
-
-namespace Drupal\Core\Database\Driver\mysql\Install;
-
-use Drupal\Core\Database\Install\Tasks as InstallTasks;
-use Drupal\Core\Database\Database;
-use Drupal\Core\Database\Driver\mysql\Connection;
-use Drupal\Core\Database\DatabaseNotFoundException;
-
-/**
- * Specifies installation tasks for MySQL and equivalent databases.
- */
-class Tasks extends InstallTasks {
-
-  /**
-   * Minimum required MySQLnd version.
-   */
-  const MYSQLND_MINIMUM_VERSION = '5.0.9';
-
-  /**
-   * Minimum required libmysqlclient version.
-   */
-  const LIBMYSQLCLIENT_MINIMUM_VERSION = '5.5.3';
-
-  /**
-   * The PDO driver name for MySQL and equivalent databases.
-   *
-   * @var string
-   */
-  protected $pdoDriver = 'mysql';
-
-  /**
-   * Constructs a \Drupal\Core\Database\Driver\mysql\Install\Tasks object.
-   */
-  public function __construct() {
-    $this->tasks[] = array(
-      'arguments' => array(),
-      'function' => 'ensureInnoDbAvailable',
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function name() {
-    return t('MySQL, MariaDB, Percona Server, or equivalent');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function minimumVersion() {
-    return '5.5.3';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function connect() {
-    try {
-      // This doesn't actually test the connection.
-      db_set_active();
-      // Now actually do a check.
-      try {
-        Database::getConnection();
-      }
-      catch (\Exception $e) {
-        // Detect utf8mb4 incompability.
-        if ($e->getCode() == Connection::UNSUPPORTED_CHARSET) {
-          $this->fail(t('Your MySQL server and PHP MySQL driver must support utf8mb4 character encoding. Make sure to use a database system that supports this (such as MySQL/MariaDB/Percona 5.5.3 and up), and that the utf8mb4 character set is compiled in. See the <a href="@documentation" target="_blank">MySQL documentation</a> for more information.', array('@documentation' => 'https://dev.mysql.com/doc/refman/5.0/en/cannot-initialize-character-set.html')));
-          $info = Database::getConnectionInfo();
-          $info_copy = $info;
-          // Set a flag to fall back to utf8. Note: this flag should only be
-          // used here and is for internal use only.
-          $info_copy['default']['_dsn_utf8_fallback'] = TRUE;
-          // In order to change the Database::$databaseInfo array, we need to
-          // remove the active connection, then re-add it with the new info.
-          Database::removeConnection('default');
-          Database::addConnectionInfo('default', 'default', $info_copy['default']);
-          // Connect with the new database info, using the utf8 character set so
-          // that we can run the checkEngineVersion test.
-          Database::getConnection();
-          // Revert to the old settings.
-          Database::removeConnection('default');
-          Database::addConnectionInfo('default', 'default', $info['default']);
-        }
-        else {
-          // Rethrow the exception.
-          throw $e;
-        }
-      }
-      $this->pass('Drupal can CONNECT to the database ok.');
-    }
-    catch (\Exception $e) {
-      // Attempt to create the database if it is not found.
-      if ($e->getCode() == Connection::DATABASE_NOT_FOUND) {
-        // Remove the database string from connection info.
-        $connection_info = Database::getConnectionInfo();
-        $database = $connection_info['default']['database'];
-        unset($connection_info['default']['database']);
-
-        // In order to change the Database::$databaseInfo array, need to remove
-        // the active connection, then re-add it with the new info.
-        Database::removeConnection('default');
-        Database::addConnectionInfo('default', 'default', $connection_info['default']);
-
-        try {
-          // Now, attempt the connection again; if it's successful, attempt to
-          // create the database.
-          Database::getConnection()->createDatabase($database);
-        }
-        catch (DatabaseNotFoundException $e) {
-          // Still no dice; probably a permission issue. Raise the error to the
-          // installer.
-          $this->fail(t('Database %database not found. The server reports the following message when attempting to create the database: %error.', array('%database' => $database, '%error' => $e->getMessage())));
-        }
-      }
-      else {
-        // Database connection failed for some other reason than the database
-        // not existing.
-        $this->fail(t('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 or does the database user have sufficient privileges to create the database?</li><li>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;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormOptions(array $database) {
-    $form = parent::getFormOptions($database);
-    if (empty($form['advanced_options']['port']['#default_value'])) {
-      $form['advanced_options']['port']['#default_value'] = '3306';
-    }
-
-    return $form;
-  }
-
-  /**
-   * Ensure that InnoDB is available.
-   */
-  function ensureInnoDbAvailable() {
-    $engines = Database::getConnection()->query('SHOW ENGINES')->fetchAllKeyed();
-    if (isset($engines['MyISAM']) && $engines['MyISAM'] == 'DEFAULT' && !isset($engines['InnoDB'])) {
-      $this->fail(t('The MyISAM storage engine is not supported.'));
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function checkEngineVersion() {
-    parent::checkEngineVersion();
-
-    // Ensure that the MySQL driver supports utf8mb4 encoding.
-    $version = Database::getConnection()->clientVersion();
-    if (FALSE !== strpos($version, 'mysqlnd')) {
-      // The mysqlnd driver supports utf8mb4 starting at version 5.0.9.
-      $version = preg_replace('/^\D+([\d.]+).*/', '$1', $version);
-      if (version_compare($version, self::MYSQLND_MINIMUM_VERSION, '<')) {
-        $this->fail(t("The MySQLnd driver version %version is less than the minimum required version. Upgrade to MySQLnd version %mysqlnd_minimum_version or up, or alternatively switch mysql drivers to libmysqlclient version %libmysqlclient_minimum_version or up.", array('%version' => $version, '%mysqlnd_minimum_version' => self::MYSQLND_MINIMUM_VERSION, '%libmysqlclient_minimum_version' => self::LIBMYSQLCLIENT_MINIMUM_VERSION)));
-      }
-    }
-    else {
-      // The libmysqlclient driver supports utf8mb4 starting at version 5.5.3.
-      if (version_compare($version, self::LIBMYSQLCLIENT_MINIMUM_VERSION, '<')) {
-        $this->fail(t("The libmysqlclient driver version %version is less than the minimum required version. Upgrade to libmysqlclient version %libmysqlclient_minimum_version or up, or alternatively switch mysql drivers to MySQLnd version %mysqlnd_minimum_version or up.", array('%version' => $version, '%libmysqlclient_minimum_version' => self::LIBMYSQLCLIENT_MINIMUM_VERSION, '%mysqlnd_minimum_version' => self::MYSQLND_MINIMUM_VERSION)));
-      }
-    }
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Merge.php b/core/lib/Drupal/Core/Database/Driver/mysql/Merge.php
deleted file mode 100644
index b98d868..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Merge.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
deleted file mode 100644
index 28552fa..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
+++ /dev/null
@@ -1,602 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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\SchemaException;
-use Drupal\Core\Database\SchemaObjectExistsException;
-use Drupal\Core\Database\SchemaObjectDoesNotExistException;
-use Drupal\Core\Database\Schema as DatabaseSchema;
-use Drupal\Component\Utility\Unicode;
-
-/**
- * @addtogroup schemaapi
- * @{
- */
-
-class Schema extends DatabaseSchema {
-
-  /**
-   * Maximum length of a table comment in MySQL.
-   */
-  const COMMENT_MAX_TABLE = 60;
-
-  /**
-   * Maximum length of a column comment in MySQL.
-   */
-  const COMMENT_MAX_COLUMN = 255;
-
-  /**
-   * @var array
-   *   List of MySQL string types.
-   */
-  protected $mysqlStringTypes = array(
-    'VARCHAR',
-    'CHAR',
-    'TINYTEXT',
-    'MEDIUMTEXT',
-    'LONGTEXT',
-    'TEXT',
-  );
-
-  /**
-   * Get information about the table and database name from the prefix.
-   *
-   * @return
-   *   A keyed array with information about the database, table name and prefix.
-   */
-  protected function getPrefixInfo($table = 'default', $add_prefix = TRUE) {
-    $info = array('prefix' => $this->connection->tablePrefix($table));
-    if ($add_prefix) {
-      $table = $info['prefix'] . $table;
-    }
-    if (($pos = strpos($table, '.')) !== FALSE) {
-      $info['database'] = substr($table, 0, $pos);
-      $info['table'] = substr($table, ++$pos);
-    }
-    else {
-      $info['database'] = $this->connection->getConnectionOptions()['database'];
-      $info['table'] = $table;
-    }
-    return $info;
-  }
-
-  /**
-   * Build a condition to match a table name against a standard information_schema.
-   *
-   * MySQL uses databases like schemas rather than catalogs so when we build
-   * a condition to query the information_schema.tables, we set the default
-   * database as the schema unless specified otherwise, and exclude table_catalog
-   * from the condition criteria.
-   */
-  protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) {
-    $table_info = $this->getPrefixInfo($table_name, $add_prefix);
-
-    $condition = new Condition('AND');
-    $condition->condition('table_schema', $table_info['database']);
-    $condition->condition('table_name', $table_info['table'], $operator);
-    return $condition;
-  }
-
-  /**
-   * Generate SQL to create a new table from a Drupal schema definition.
-   *
-   * @param $name
-   *   The name of the table to create.
-   * @param $table
-   *   A Schema API table definition array.
-   * @return
-   *   An array of SQL statements to create the table.
-   */
-  protected function createTableSql($name, $table) {
-    $info = $this->connection->getConnectionOptions();
-
-    // Provide defaults if needed.
-    $table += array(
-      'mysql_engine' => 'InnoDB',
-      'mysql_character_set' => 'utf8mb4',
-    );
-
-    $sql = "CREATE TABLE {" . $name . "} (\n";
-
-    // Add the SQL statement for each field.
-    foreach ($table['fields'] as $field_name => $field) {
-      $sql .= $this->createFieldSql($field_name, $this->processField($field)) . ", \n";
-    }
-
-    // Process keys & indexes.
-    $keys = $this->createKeysSql($table);
-    if (count($keys)) {
-      $sql .= implode(", \n", $keys) . ", \n";
-    }
-
-    // Remove the last comma and space.
-    $sql = substr($sql, 0, -3) . "\n) ";
-
-    $sql .= 'ENGINE = ' . $table['mysql_engine'] . ' DEFAULT CHARACTER SET ' . $table['mysql_character_set'];
-    // By default, MySQL uses the default collation for new tables, which is
-    // 'utf8mb4_general_ci' for utf8mb4. If an alternate collation has been
-    // set, it needs to be explicitly specified.
-    // @see DatabaseConnection_mysql
-    if (!empty($info['collation'])) {
-      $sql .= ' COLLATE ' . $info['collation'];
-    }
-
-    // Add table comment.
-    if (!empty($table['description'])) {
-      $sql .= ' COMMENT ' . $this->prepareComment($table['description'], self::COMMENT_MAX_TABLE);
-    }
-
-    return array($sql);
-  }
-
-  /**
-   * Create an SQL string for a field to be used in table creation or alteration.
-   *
-   * Before passing a field out of a schema definition into this function it has
-   * to be processed by _db_process_field().
-   *
-   * @param string $name
-   *   Name of the field.
-   * @param array $spec
-   *   The field specification, as per the schema data structure format.
-   */
-  protected function createFieldSql($name, $spec) {
-    $sql = "`" . $name . "` " . $spec['mysql_type'];
-
-    if (in_array($spec['mysql_type'], $this->mysqlStringTypes)) {
-      if (isset($spec['length'])) {
-        $sql .= '(' . $spec['length'] . ')';
-      }
-      if (!empty($spec['binary'])) {
-        $sql .= ' BINARY';
-      }
-      // Note we check for the "type" key here. "mysql_type" is VARCHAR:
-      if (isset($spec['type']) && $spec['type'] == 'varchar_ascii') {
-        $sql .= ' CHARACTER SET ascii COLLATE ascii_general_ci';
-      }
-    }
-    elseif (isset($spec['precision']) && isset($spec['scale'])) {
-      $sql .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
-    }
-
-    if (!empty($spec['unsigned'])) {
-      $sql .= ' unsigned';
-    }
-
-    if (isset($spec['not null'])) {
-      if ($spec['not null']) {
-        $sql .= ' NOT NULL';
-      }
-      else {
-        $sql .= ' NULL';
-      }
-    }
-
-    if (!empty($spec['auto_increment'])) {
-      $sql .= ' auto_increment';
-    }
-
-    // $spec['default'] can be NULL, so we explicitly check for the key here.
-    if (array_key_exists('default', $spec)) {
-      $sql .= ' DEFAULT ' . $this->escapeDefaultValue($spec['default']);
-    }
-
-    if (empty($spec['not null']) && !isset($spec['default'])) {
-      $sql .= ' DEFAULT NULL';
-    }
-
-    // Add column comment.
-    if (!empty($spec['description'])) {
-      $sql .= ' COMMENT ' . $this->prepareComment($spec['description'], self::COMMENT_MAX_COLUMN);
-    }
-
-    return $sql;
-  }
-
-  /**
-   * Set database-engine specific properties for a field.
-   *
-   * @param $field
-   *   A field description array, as specified in the schema documentation.
-   */
-  protected function processField($field) {
-
-    if (!isset($field['size'])) {
-      $field['size'] = 'normal';
-    }
-
-    // Set the correct database-engine specific datatype.
-    // In case one is already provided, force it to uppercase.
-    if (isset($field['mysql_type'])) {
-      $field['mysql_type'] = Unicode::strtoupper($field['mysql_type']);
-    }
-    else {
-      $map = $this->getFieldTypeMap();
-      $field['mysql_type'] = $map[$field['type'] . ':' . $field['size']];
-    }
-
-    if (isset($field['type']) && $field['type'] == 'serial') {
-      $field['auto_increment'] = TRUE;
-    }
-
-    return $field;
-  }
-
-  public function getFieldTypeMap() {
-    // Put :normal last so it gets preserved by array_flip. This makes
-    // it much easier for modules (such as schema.module) to map
-    // database types back into schema types.
-    // $map does not use drupal_static as its value never changes.
-    static $map = array(
-      'varchar_ascii:normal' => 'VARCHAR',
-
-      'varchar:normal'  => 'VARCHAR',
-      'char:normal'     => 'CHAR',
-
-      'text:tiny'       => 'TINYTEXT',
-      'text:small'      => 'TINYTEXT',
-      'text:medium'     => 'MEDIUMTEXT',
-      'text:big'        => 'LONGTEXT',
-      'text:normal'     => 'TEXT',
-
-      'serial:tiny'     => 'TINYINT',
-      'serial:small'    => 'SMALLINT',
-      'serial:medium'   => 'MEDIUMINT',
-      'serial:big'      => 'BIGINT',
-      'serial:normal'   => 'INT',
-
-      'int:tiny'        => 'TINYINT',
-      'int:small'       => 'SMALLINT',
-      'int:medium'      => 'MEDIUMINT',
-      'int:big'         => 'BIGINT',
-      'int:normal'      => 'INT',
-
-      'float:tiny'      => 'FLOAT',
-      'float:small'     => 'FLOAT',
-      'float:medium'    => 'FLOAT',
-      'float:big'       => 'DOUBLE',
-      'float:normal'    => 'FLOAT',
-
-      'numeric:normal'  => 'DECIMAL',
-
-      'blob:big'        => 'LONGBLOB',
-      'blob:normal'     => 'BLOB',
-    );
-    return $map;
-  }
-
-  protected function createKeysSql($spec) {
-    $keys = array();
-
-    if (!empty($spec['primary key'])) {
-      $keys[] = 'PRIMARY KEY (' . $this->createKeySql($spec['primary key']) . ')';
-    }
-    if (!empty($spec['unique keys'])) {
-      foreach ($spec['unique keys'] as $key => $fields) {
-        $keys[] = 'UNIQUE KEY `' . $key . '` (' . $this->createKeySql($fields) . ')';
-      }
-    }
-    if (!empty($spec['indexes'])) {
-      $indexes = $this->getNormalizedIndexes($spec);
-      foreach ($indexes as $index => $fields) {
-        $keys[] = 'INDEX `' . $index . '` (' . $this->createKeySql($fields) . ')';
-      }
-    }
-
-    return $keys;
-  }
-
-  /**
-   * Gets normalized indexes from a table specification.
-   *
-   * Shortens indexes to 191 characters if they apply to utf8mb4-encoded
-   * fields, in order to comply with the InnoDB index limitation of 756 bytes.
-   *
-   * @param array $spec
-   *   The table specification.
-   *
-   * @return array
-   *   List of shortened indexes.
-   *
-   * @throws \Drupal\Core\Database\SchemaException
-   *   Thrown if field specification is missing.
-   */
-  protected function getNormalizedIndexes(array $spec) {
-    $indexes = isset($spec['indexes']) ? $spec['indexes'] : [];
-    foreach ($indexes as $index_name => $index_fields) {
-      foreach ($index_fields as $index_key => $index_field) {
-        // Get the name of the field from the index specification.
-        $field_name = is_array($index_field) ? $index_field[0] : $index_field;
-        // Check whether the field is defined in the table specification.
-        if (isset($spec['fields'][$field_name])) {
-          // Get the MySQL type from the processed field.
-          $mysql_field = $this->processField($spec['fields'][$field_name]);
-          if (in_array($mysql_field['mysql_type'], $this->mysqlStringTypes)) {
-            // Check whether we need to shorten the index.
-            if ((!isset($mysql_field['type']) || $mysql_field['type'] != 'varchar_ascii') && (!isset($mysql_field['length']) || $mysql_field['length'] > 191)) {
-              // Limit the index length to 191 characters.
-              $this->shortenIndex($indexes[$index_name][$index_key]);
-            }
-          }
-        }
-        else {
-          throw new SchemaException("MySQL needs the '$field_name' field specification in order to normalize the '$index_name' index");
-        }
-      }
-    }
-    return $indexes;
-  }
-
-  /**
-   * Helper function for normalizeIndexes().
-   *
-   * Shortens an index to 191 characters.
-   *
-   * @param array $index
-   *   The index array to be used in createKeySql.
-   *
-   * @see Drupal\Core\Database\Driver\mysql\Schema::createKeySql()
-   * @see Drupal\Core\Database\Driver\mysql\Schema::normalizeIndexes()
-   */
-  protected function shortenIndex(&$index) {
-    if (is_array($index)) {
-      if ($index[1] > 191) {
-        $index[1] = 191;
-      }
-    }
-    else {
-      $index = array($index, 191);
-    }
-  }
-
-  protected function createKeySql($fields) {
-    $return = array();
-    foreach ($fields as $field) {
-      if (is_array($field)) {
-        $return[] = '`' . $field[0] . '`(' . $field[1] . ')';
-      }
-      else {
-        $return[] = '`' . $field . '`';
-      }
-    }
-    return implode(', ', $return);
-  }
-
-  public function renameTable($table, $new_name) {
-    if (!$this->tableExists($table)) {
-      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 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);
-    return $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO `' . $info['table'] . '`');
-  }
-
-  public function dropTable($table) {
-    if (!$this->tableExists($table)) {
-      return FALSE;
-    }
-
-    $this->connection->query('DROP TABLE {' . $table . '}');
-    return TRUE;
-  }
-
-  public function addField($table, $field, $spec, $keys_new = array()) {
-    if (!$this->tableExists($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 SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
-    }
-
-    $fixnull = FALSE;
-    if (!empty($spec['not null']) && !isset($spec['default'])) {
-      $fixnull = TRUE;
-      $spec['not null'] = FALSE;
-    }
-    $query = 'ALTER TABLE {' . $table . '} ADD ';
-    $query .= $this->createFieldSql($field, $this->processField($spec));
-    if ($keys_sql = $this->createKeysSql($keys_new)) {
-      $query .= ', ADD ' . implode(', ADD ', $keys_sql);
-    }
-    $this->connection->query($query);
-    if (isset($spec['initial'])) {
-      $this->connection->update($table)
-        ->fields(array($field => $spec['initial']))
-        ->execute();
-    }
-    if ($fixnull) {
-      $spec['not null'] = TRUE;
-      $this->changeField($table, $field, $field, $spec);
-    }
-  }
-
-  public function dropField($table, $field) {
-    if (!$this->fieldExists($table, $field)) {
-      return FALSE;
-    }
-
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP `' . $field . '`');
-    return TRUE;
-  }
-
-  public function fieldSetDefault($table, $field, $default) {
-    if (!$this->fieldExists($table, $field)) {
-      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
-    }
-
-    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN `' . $field . '` SET DEFAULT ' . $this->escapeDefaultValue($default));
-  }
-
-  public function fieldSetNoDefault($table, $field) {
-    if (!$this->fieldExists($table, $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');
-  }
-
-  public function indexExists($table, $name) {
-    // Returns one row for each column in the index. Result is string or FALSE.
-    // Details at http://dev.mysql.com/doc/refman/5.0/en/show-index.html
-    $row = $this->connection->query('SHOW INDEX FROM {' . $table . '} WHERE key_name = ' . $this->connection->quote($name))->fetchAssoc();
-    return isset($row['Key_name']);
-  }
-
-  public function addPrimaryKey($table, $fields) {
-    if (!$this->tableExists($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 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) . ')');
-  }
-
-  public function dropPrimaryKey($table) {
-    if (!$this->indexExists($table, 'PRIMARY')) {
-      return FALSE;
-    }
-
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP PRIMARY KEY');
-    return TRUE;
-  }
-
-  public function addUniqueKey($table, $name, $fields) {
-    if (!$this->tableExists($table)) {
-      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 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) . ')');
-  }
-
-  public function dropUniqueKey($table, $name) {
-    if (!$this->indexExists($table, $name)) {
-      return FALSE;
-    }
-
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP KEY `' . $name . '`');
-    return TRUE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function addIndex($table, $name, $fields, array $spec) {
-    if (!$this->tableExists($table)) {
-      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 SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
-    }
-
-    $spec['indexes'][$name] = $fields;
-    $indexes = $this->getNormalizedIndexes($spec);
-
-    $this->connection->query('ALTER TABLE {' . $table . '} ADD INDEX `' . $name . '` (' . $this->createKeySql($indexes[$name]) . ')');
-  }
-
-  public function dropIndex($table, $name) {
-    if (!$this->indexExists($table, $name)) {
-      return FALSE;
-    }
-
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP INDEX `' . $name . '`');
-    return TRUE;
-  }
-
-  public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
-    if (!$this->fieldExists($table, $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 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));
-    if ($keys_sql = $this->createKeysSql($keys_new)) {
-      $sql .= ', ADD ' . implode(', ADD ', $keys_sql);
-    }
-    $this->connection->query($sql);
-  }
-
-  public function prepareComment($comment, $length = NULL) {
-    // Truncate comment to maximum comment length.
-    if (isset($length)) {
-      // Add table prefixes before truncating.
-      $comment = Unicode::truncate($this->connection->prefixTables($comment), $length, TRUE, TRUE);
-    }
-
-    return $this->connection->quote($comment);
-  }
-
-  /**
-   * Retrieve a table or column comment.
-   */
-  public function getComment($table, $column = NULL) {
-    $condition = $this->buildTableNameCondition($table);
-    if (isset($column)) {
-      $condition->condition('column_name', $column);
-      $condition->compile($this->connection, $this);
-      // Don't use {} around information_schema.columns table.
-      return $this->connection->query("SELECT column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField();
-    }
-    $condition->compile($this->connection, $this);
-    // Don't use {} around information_schema.tables table.
-    $comment = $this->connection->query("SELECT table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField();
-    // Work-around for MySQL 5.0 bug http://bugs.mysql.com/bug.php?id=11379
-    return preg_replace('/; InnoDB free:.*$/', '', $comment);
-  }
-
-  public function tableExists($table) {
-    // The information_schema table is very slow to query under MySQL 5.0.
-    // Instead, we try to select from the table in question.  If it fails,
-    // the most likely reason is that it does not exist. That is dramatically
-    // faster than using information_schema.
-    // @link http://bugs.mysql.com/bug.php?id=19588
-    // @todo This override should be removed once we require a version of MySQL
-    //   that has that bug fixed.
-    try {
-      $this->connection->queryRange("SELECT 1 FROM {" . $table . "}", 0, 1);
-      return TRUE;
-    }
-    catch (\Exception $e) {
-      return FALSE;
-    }
-  }
-
-  public function fieldExists($table, $column) {
-    // The information_schema table is very slow to query under MySQL 5.0.
-    // Instead, we try to select from the table and field in question. If it
-    // fails, the most likely reason is that it does not exist. That is
-    // dramatically faster than using information_schema.
-    // @link http://bugs.mysql.com/bug.php?id=19588
-    // @todo This override should be removed once we require a version of MySQL
-    //   that has that bug fixed.
-    try {
-      $this->connection->queryRange("SELECT $column FROM {" . $table . "}", 0, 1);
-      return TRUE;
-    }
-    catch (\Exception $e) {
-      return FALSE;
-    }
-  }
-
-}
-
-/**
- * @} End of "addtogroup schemaapi".
- */
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Select.php b/core/lib/Drupal/Core/Database/Driver/mysql/Select.php
deleted file mode 100644
index caa2dbf..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Select.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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
deleted file mode 100644
index a04d7a0..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Transaction.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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
deleted file mode 100644
index 00cf10c..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Truncate.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\mysql\Truncate.
- */
-
-namespace Drupal\Core\Database\Driver\mysql;
-
-use Drupal\Core\Database\Query\Truncate as QueryTruncate;
-
-class Truncate extends QueryTruncate { }
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Update.php b/core/lib/Drupal/Core/Database/Driver/mysql/Update.php
deleted file mode 100644
index 7d96e55..0000000
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Update.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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/lib/Drupal/Core/Database/Driver/pgsql/Connection.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
deleted file mode 100644
index ff38a22..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
+++ /dev/null
@@ -1,406 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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\DatabaseNotFoundException;
-use Drupal\Core\Database\StatementInterface;
-use Drupal\Core\Database\IntegrityConstraintViolationException;
-use Drupal\Core\Database\DatabaseExceptionWrapper;
-
-/**
- * @addtogroup database
- * @{
- */
-
-class Connection extends DatabaseConnection {
-
-  /**
-   * The name by which to obtain a lock for retrieve the next insert id.
-   */
-  const POSTGRESQL_NEXTID_LOCK = 1000;
-
-  /**
-   * Error code for "Unknown database" error.
-   */
-  const DATABASE_NOT_FOUND = 7;
-
-  /**
-   * The list of PostgreSQL reserved key words.
-   *
-   * @see http://www.postgresql.org/docs/9.4/static/sql-keywords-appendix.html
-   */
-  protected $postgresqlReservedKeyWords = ['all', 'analyse', 'analyze', 'and',
-  'any', 'array', 'as', 'asc', 'asymmetric', 'authorization', 'binary', 'both',
-  'case', 'cast', 'check', 'collate', 'collation', 'column', 'concurrently',
-  'constraint', 'create', 'cross', 'current_catalog', 'current_date',
-  'current_role', 'current_schema', 'current_time', 'current_timestamp',
-  'current_user', 'default', 'deferrable', 'desc', 'distinct', 'do', 'else',
-  'end', 'except', 'false', 'fetch', 'for', 'foreign', 'freeze', 'from', 'full',
-  'grant', 'group', 'having', 'ilike', 'in', 'initially', 'inner', 'intersect',
-  'into', 'is', 'isnull', 'join', 'lateral', 'leading', 'left', 'like', 'limit',
-  'localtime', 'localtimestamp', 'natural', 'not', 'notnull', 'null', 'offset',
-  'on', 'only', 'or', 'order', 'outer', 'over', 'overlaps', 'placing',
-  'primary', 'references', 'returning', 'right', 'select', 'session_user',
-  'similar', 'some', 'symmetric', 'table', 'then', 'to', 'trailing', 'true',
-  'union', 'unique', 'user', 'using', 'variadic', 'verbose', 'when', 'where',
-  'window', 'with'];
-
-  /**
-   * Constructs a connection object.
-   */
-  public function __construct(\PDO $connection, array $connection_options) {
-    parent::__construct($connection, $connection_options);
-
-    // This driver defaults to transaction support, except if explicitly passed FALSE.
-    $this->transactionSupport = !isset($connection_options['transactions']) || ($connection_options['transactions'] !== FALSE);
-
-    // Transactional DDL is always available in PostgreSQL,
-    // but we'll only enable it if standard transactions are.
-    $this->transactionalDDLSupport = $this->transactionSupport;
-
-    $this->connectionOptions = $connection_options;
-
-    // Force PostgreSQL to use the UTF-8 character set by default.
-    $this->connection->exec("SET NAMES 'UTF8'");
-
-    // Execute PostgreSQL init_commands.
-    if (isset($connection_options['init_commands'])) {
-      $this->connection->exec(implode('; ', $connection_options['init_commands']));
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function open(array &$connection_options = array()) {
-    // Default to TCP connection on port 5432.
-    if (empty($connection_options['port'])) {
-      $connection_options['port'] = 5432;
-    }
-
-    // PostgreSQL in trust mode doesn't require a password to be supplied.
-    if (empty($connection_options['password'])) {
-      $connection_options['password'] = NULL;
-    }
-    // If the password contains a backslash it is treated as an escape character
-    // http://bugs.php.net/bug.php?id=53217
-    // so backslashes in the password need to be doubled up.
-    // The bug was reported against pdo_pgsql 1.0.2, backslashes in passwords
-    // will break on this doubling up when the bug is fixed, so check the version
-    //elseif (phpversion('pdo_pgsql') < 'version_this_was_fixed_in') {
-    else {
-      $connection_options['password'] = str_replace('\\', '\\\\', $connection_options['password']);
-    }
-
-    $connection_options['database'] = (!empty($connection_options['database']) ? $connection_options['database'] : 'template1');
-    $dsn = 'pgsql:host=' . $connection_options['host'] . ' dbname=' . $connection_options['database'] . ' port=' . $connection_options['port'];
-
-    // Allow PDO options to be overridden.
-    $connection_options += array(
-      'pdo' => array(),
-    );
-    $connection_options['pdo'] += array(
-      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
-      // Prepared statements are most effective for performance when queries
-      // are recycled (used several times). However, if they are not re-used,
-      // prepared statements become inefficient. Since most of Drupal's
-      // prepared queries are not re-used, it should be faster to emulate
-      // the preparation than to actually ready statements for re-use. If in
-      // doubt, reset to FALSE and measure performance.
-      \PDO::ATTR_EMULATE_PREPARES => TRUE,
-      // Convert numeric values to strings when fetching.
-      \PDO::ATTR_STRINGIFY_FETCHES => TRUE,
-    );
-    $pdo = new \PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
-
-    return $pdo;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function query($query, array $args = array(), $options = array()) {
-    $options += $this->defaultOptions();
-
-    // The PDO PostgreSQL driver has a bug which doesn't type cast booleans
-    // correctly when parameters are bound using associative arrays.
-    // @see http://bugs.php.net/bug.php?id=48383
-    foreach ($args as &$value) {
-      if (is_bool($value)) {
-        $value = (int) $value;
-      }
-    }
-
-    return parent::query($query, $args, $options);
-  }
-
-  public function prepareQuery($query) {
-    // mapConditionOperator converts LIKE operations to ILIKE for consistency
-    // with MySQL. However, Postgres does not support ILIKE on bytea (blobs)
-    // fields.
-    // To make the ILIKE operator work, we type-cast bytea fields into text.
-    // @todo This workaround only affects bytea fields, but the involved field
-    //   types involved in the query are unknown, so there is no way to
-    //   conditionally execute this for affected queries only.
-    return parent::prepareQuery(preg_replace('/ ([^ ]+) +(I*LIKE|NOT +I*LIKE) /i', ' ${1}::text ${2} ', $query));
-  }
-
-  public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
-    return $this->query($query . ' LIMIT ' . (int) $count . ' OFFSET ' . (int) $from, $args, $options);
-  }
-
-  public function queryTemporary($query, array $args = array(), array $options = array()) {
-    $tablename = $this->generateTemporaryTableName();
-    $this->query('CREATE TEMPORARY TABLE {' . $tablename . '} AS ' . $query, $args, $options);
-    return $tablename;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function escapeField($field) {
-    $escaped = parent::escapeField($field);
-
-    // Remove any invalid start character.
-    $escaped = preg_replace('/^[^A-Za-z0-9_]/', '', $escaped);
-
-    // The pgsql database driver does not support field names that contain
-    // periods (supported by PostgreSQL server) because this method may be
-    // called by a field with a table alias as part of SQL conditions or
-    // order by statements. This will consider a period as a table alias
-    // identifier, and split the string at the first period.
-    if (preg_match('/^([A-Za-z0-9_]+)"?[.]"?([A-Za-z0-9_.]+)/', $escaped, $parts)) {
-      $table = $parts[1];
-      $column = $parts[2];
-
-      // Use escape alias because escapeField may contain multiple periods that
-      // need to be escaped.
-      $escaped = $this->escapeTable($table) . '.' . $this->escapeAlias($column);
-    }
-    elseif (preg_match('/[A-Z]/', $escaped)) {
-      // Quote the field name for case-sensitivity.
-      $escaped = '"' . $escaped . '"';
-    }
-    elseif (in_array(strtolower($escaped), $this->postgresqlReservedKeyWords)) {
-      // Quote the field name for PostgreSQL reserved key words.
-      $escaped = '"' . $escaped . '"';
-    }
-
-    return $escaped;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function escapeAlias($field) {
-    $escaped = preg_replace('/[^A-Za-z0-9_]+/', '', $field);
-
-    // Escape the alias in quotes for case-sensitivity.
-    if (preg_match('/[A-Z]/', $escaped)) {
-      $escaped = '"' . $escaped . '"';
-    }
-    elseif (in_array(strtolower($escaped), $this->postgresqlReservedKeyWords)) {
-      // Quote the alias name for PostgreSQL reserved key words.
-      $escaped = '"' . $escaped . '"';
-    }
-
-    return $escaped;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function escapeTable($table) {
-    $escaped = parent::escapeTable($table);
-
-    // Quote identifier to make it case-sensitive.
-    if (preg_match('/[A-Z]/', $escaped)) {
-      $escaped = '"' . $escaped . '"';
-    }
-    elseif (in_array(strtolower($escaped), $this->postgresqlReservedKeyWords)) {
-      // Quote the table name for PostgreSQL reserved key words.
-      $escaped = '"' . $escaped . '"';
-    }
-
-    return $escaped;
-  }
-
-  public function driver() {
-    return 'pgsql';
-  }
-
-  public function databaseType() {
-    return 'pgsql';
-  }
-
-  /**
-   * Overrides \Drupal\Core\Database\Connection::createDatabase().
-   *
-   * @param string $database
-   *   The name of the database to create.
-   *
-   * @throws \Drupal\Core\Database\DatabaseNotFoundException
-   */
-  public function createDatabase($database) {
-    // Escape the database name.
-    $database = Database::getConnection()->escapeDatabase($database);
-
-    // If the PECL intl extension is installed, use it to determine the proper
-    // locale.  Otherwise, fall back to en_US.
-    if (class_exists('Locale')) {
-      $locale = \Locale::getDefault();
-    }
-    else {
-      $locale = 'en_US';
-    }
-
-    try {
-      // Create the database and set it as active.
-      $this->connection->exec("CREATE DATABASE $database WITH TEMPLATE template0 ENCODING='utf8' LC_CTYPE='$locale.utf8' LC_COLLATE='$locale.utf8'");
-    }
-    catch (\Exception $e) {
-      throw new DatabaseNotFoundException($e->getMessage());
-    }
-  }
-
-  public function mapConditionOperator($operator) {
-    static $specials = array(
-      // In PostgreSQL, 'LIKE' is case-sensitive. For case-insensitive LIKE
-      // statements, we need to use ILIKE instead.
-      'LIKE' => array('operator' => 'ILIKE'),
-      'LIKE BINARY' => array('operator' => 'LIKE'),
-      'NOT LIKE' => array('operator' => 'NOT ILIKE'),
-      'REGEXP' => array('operator' => '~*'),
-    );
-    return isset($specials[$operator]) ? $specials[$operator] : NULL;
-  }
-
-  /**
-   * Retrieve a the next id in a sequence.
-   *
-   * PostgreSQL has built in sequences. We'll use these instead of inserting
-   * and updating a sequences table.
-   */
-  public function nextId($existing = 0) {
-
-    // Retrieve the name of the sequence. This information cannot be cached
-    // because the prefix may change, for example, like it does in simpletests.
-    $sequence_name = $this->makeSequenceName('sequences', 'value');
-
-    // When PostgreSQL gets a value too small then it will lock the table,
-    // retry the INSERT and if it's still too small then alter the sequence.
-    $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
-    if ($id > $existing) {
-      return $id;
-    }
-
-    // PostgreSQL advisory locks are simply locks to be used by an
-    // application such as Drupal. This will prevent other Drupal processes
-    // from altering the sequence while we are.
-    $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(" . self::POSTGRESQL_NEXTID_LOCK . ")");
-      return $id;
-    }
-
-    // Reset the sequence to a higher value than the existing id.
-    $this->query("ALTER SEQUENCE " . $sequence_name . " RESTART WITH " . ($existing + 1));
-
-    // Retrieve 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(" . self::POSTGRESQL_NEXTID_LOCK . ")");
-
-    return $id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFullQualifiedTableName($table) {
-    $options = $this->getConnectionOptions();
-    $prefix = $this->tablePrefix($table);
-
-    // The fully qualified table name in PostgreSQL is in the form of
-    // <database>.<schema>.<table>, so we have to include the 'public' schema in
-    // the return value.
-    return $options['database'] . '.public.' . $prefix . $table;
-  }
-
-  /**
-   * Add a new savepoint with an unique name.
-   *
-   * The main use for this method is to mimic InnoDB functionality, which
-   * provides an inherent savepoint before any query in a transaction.
-   *
-   * @param $savepoint_name
-   *   A string representing the savepoint name. By default,
-   *   "mimic_implicit_commit" is used.
-   *
-   * @see Drupal\Core\Database\Connection::pushTransaction().
-   */
-  public function addSavepoint($savepoint_name = 'mimic_implicit_commit') {
-    if ($this->inTransaction()) {
-      $this->pushTransaction($savepoint_name);
-    }
-  }
-
-  /**
-   * Release a savepoint by name.
-   *
-   * @param $savepoint_name
-   *   A string representing the savepoint name. By default,
-   *   "mimic_implicit_commit" is used.
-   *
-   * @see Drupal\Core\Database\Connection::popTransaction().
-   */
-  public function releaseSavepoint($savepoint_name = 'mimic_implicit_commit') {
-    if (isset($this->transactionLayers[$savepoint_name])) {
-      $this->popTransaction($savepoint_name);
-    }
-  }
-
-  /**
-   * Rollback a savepoint by name if it exists.
-   *
-   * @param $savepoint_name
-   *   A string representing the savepoint name. By default,
-   *   "mimic_implicit_commit" is used.
-   */
-  public function rollbackSavepoint($savepoint_name = 'mimic_implicit_commit') {
-    if (isset($this->transactionLayers[$savepoint_name])) {
-      $this->rollback($savepoint_name);
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function upsert($table, array $options = array()) {
-    // Use the (faster) native Upsert implementation for PostgreSQL >= 9.5.
-    if (version_compare($this->version(), '9.5', '>=')) {
-      $class = $this->getDriverClass('NativeUpsert');
-    }
-    else {
-      $class = $this->getDriverClass('Upsert');
-    }
-
-    return new $class($this, $table, $options);
-  }
-
-}
-
-/**
- * @} End of "addtogroup database".
- */
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php
deleted file mode 100644
index f8940ad..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\pgsql\Delete.
- */
-
-namespace Drupal\Core\Database\Driver\pgsql;
-
-use Drupal\Core\Database\Query\Delete as QueryDelete;
-
-class Delete extends QueryDelete {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function execute() {
-    $this->connection->addSavepoint();
-    try {
-      $result = parent::execute();
-    }
-    catch (\Exception $e) {
-      $this->connection->rollbackSavepoint();
-      throw $e;
-    }
-    $this->connection->releaseSavepoint();
-
-    return $result;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php
deleted file mode 100644
index f36f509..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Insert.php
+++ /dev/null
@@ -1,137 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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;
-
-/**
- * @ingroup database
- * @{
- */
-
-class Insert extends QueryInsert {
-
-  public function execute() {
-    if (!$this->preExecute()) {
-      return NULL;
-    }
-
-    $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);
-
-    $max_placeholder = 0;
-    $blobs = array();
-    $blob_count = 0;
-    foreach ($this->insertValues as $insert_values) {
-      foreach ($this->insertFields as $idx => $field) {
-        if (isset($table_information->blob_fields[$field])) {
-          $blobs[$blob_count] = fopen('php://memory', 'a');
-          fwrite($blobs[$blob_count], $insert_values[$idx]);
-          rewind($blobs[$blob_count]);
-
-          $stmt->bindParam(':db_insert_placeholder_' . $max_placeholder++, $blobs[$blob_count], \PDO::PARAM_LOB);
-
-          // Pre-increment is faster in PHP than increment.
-          ++$blob_count;
-        }
-        else {
-          $stmt->bindParam(':db_insert_placeholder_' . $max_placeholder++, $insert_values[$idx]);
-        }
-      }
-      // Check if values for a serial field has been passed.
-      if (!empty($table_information->serial_fields)) {
-        foreach ($table_information->serial_fields as $index => $serial_field) {
-          $serial_key = array_search($serial_field, $this->insertFields);
-          if ($serial_key !== FALSE) {
-            $serial_value = $insert_values[$serial_key];
-
-            // Force $last_insert_id to the specified value. This is only done
-            // if $index is 0.
-            if ($index == 0) {
-              $last_insert_id = $serial_value;
-            }
-            // Sequences must be greater than or equal to 1.
-            if ($serial_value === NULL || !$serial_value) {
-              $serial_value = 1;
-            }
-            // Set the sequence to the bigger value of either the passed
-            // value or the max value of the column. It can happen that another
-            // thread calls nextval() which could lead to a serial number being
-            // used twice. However, trying to insert a value into a serial
-            // column should only be done in very rare cases and is not thread
-            // safe by definition.
-            $this->connection->query("SELECT setval('" . $table_information->sequences[$index] . "', GREATEST(MAX(" . $serial_field . "), :serial_value)) FROM {" . $this->table . "}", array(':serial_value' => (int)$serial_value));
-          }
-        }
-      }
-    }
-    if (!empty($this->fromQuery)) {
-      // bindParam stores only a reference to the variable that is followed when
-      // the statement is executed. We pass $arguments[$key] instead of $value
-      // because the second argument to bindParam is passed by reference and
-      // the foreach statement assigns the element to the existing reference.
-      $arguments = $this->fromQuery->getArguments();
-      foreach ($arguments as $key => $value) {
-        $stmt->bindParam($key, $arguments[$key]);
-      }
-    }
-
-    // PostgreSQL requires the table name to be specified explicitly
-    // when requesting the last insert ID, so we pass that in via
-    // the options array.
-    $options = $this->queryOptions;
-
-    if (!empty($table_information->sequences)) {
-      $options['sequence_name'] = $table_information->sequences[0];
-    }
-    // If there are no sequences then we can't get a last insert id.
-    elseif ($options['return'] == Database::RETURN_INSERT_ID) {
-      $options['return'] = Database::RETURN_NULL;
-    }
-    // Only use the returned last_insert_id if it is not already set.
-    if (!empty($last_insert_id)) {
-      $this->connection->query($stmt, array(), $options);
-    }
-    else {
-      $last_insert_id = $this->connection->query($stmt, array(), $options);
-    }
-
-    // Re-initialize the values array so that we can re-use this query.
-    $this->insertValues = array();
-
-    return $last_insert_id;
-  }
-
-  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);
-
-    $insert_fields = array_map(function($f) { return $this->connection->escapeField($f); }, $insert_fields);
-
-    // 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)) {
-      $insert_fields_string = $insert_fields ? ' (' . implode(', ', $insert_fields) . ') ' : ' ';
-      return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery;
-    }
-
-    $query = $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
-
-    $values = $this->getInsertPlaceholderFragment($this->insertValues, $this->defaultFields);
-    $query .= implode(', ', $values);
-
-    return $query;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Install/Tasks.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Install/Tasks.php
deleted file mode 100644
index ad2ac19..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Install/Tasks.php
+++ /dev/null
@@ -1,286 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\pgsql\Install\Tasks.
- */
-
-namespace Drupal\Core\Database\Driver\pgsql\Install;
-
-use Drupal\Core\Database\Database;
-use Drupal\Core\Database\Install\Tasks as InstallTasks;
-use Drupal\Core\Database\Driver\pgsql\Connection;
-use Drupal\Core\Database\DatabaseNotFoundException;
-
-/**
- * Specifies installation tasks for PostgreSQL databases.
- */
-class Tasks extends InstallTasks {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected $pdoDriver = 'pgsql';
-
-  /**
-   * Constructs a \Drupal\Core\Database\Driver\pgsql\Install\Tasks object.
-   */
-  public function __construct() {
-    $this->tasks[] = array(
-      'function' => 'checkEncoding',
-      'arguments' => array(),
-    );
-    $this->tasks[] = array(
-      'function' => 'checkBinaryOutput',
-      'arguments' => array(),
-    );
-    $this->tasks[] = array(
-      'function' => 'checkStandardConformingStrings',
-      'arguments' => array(),
-    );
-    $this->tasks[] = array(
-      'function' => 'initializeDatabase',
-      'arguments' => array(),
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function name() {
-    return t('PostgreSQL');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function minimumVersion() {
-    return '9.1.2';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  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) {
-    // Attempt to create the database if it is not found.
-      if ($e->getCode() == Connection::DATABASE_NOT_FOUND) {
-        // Remove the database string from connection info.
-        $connection_info = Database::getConnectionInfo();
-        $database = $connection_info['default']['database'];
-        unset($connection_info['default']['database']);
-
-        // In order to change the Database::$databaseInfo array, need to remove
-        // the active connection, then re-add it with the new info.
-        Database::removeConnection('default');
-        Database::addConnectionInfo('default', 'default', $connection_info['default']);
-
-        try {
-          // Now, attempt the connection again; if it's successful, attempt to
-          // create the database.
-          Database::getConnection()->createDatabase($database);
-          Database::closeConnection();
-
-          // Now, restore the database config.
-          Database::removeConnection('default');
-          $connection_info['default']['database'] = $database;
-          Database::addConnectionInfo('default', 'default', $connection_info['default']);
-
-          // Check the database connection.
-          Database::getConnection();
-          $this->pass('Drupal can CONNECT to the database ok.');
-        }
-        catch (DatabaseNotFoundException $e) {
-          // Still no dice; probably a permission issue. Raise the error to the
-          // installer.
-          $this->fail(t('Database %database not found. The server reports the following message when attempting to create the database: %error.', array('%database' => $database, '%error' => $e->getMessage())));
-        }
-      }
-      else {
-        // Database connection failed for some other reason than the database
-        // not existing.
-        $this->fail(t('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;
-  }
-
-  /**
-   * Check encoding is UTF8.
-   */
-  protected function checkEncoding() {
-    try {
-      if (db_query('SHOW server_encoding')->fetchField() == 'UTF8') {
-        $this->pass(t('Database is encoded in UTF-8'));
-      }
-      else {
-        $this->fail(t('The %driver database must use %encoding encoding to work with Drupal. Recreate the database with %encoding encoding. See !link for more details.', array(
-          '%encoding' => 'UTF8',
-          '%driver' => $this->name(),
-          '!link' => '<a href="INSTALL.pgsql.txt">INSTALL.pgsql.txt</a>'
-        )));
-      }
-    }
-    catch (\Exception $e) {
-      $this->fail(t('Drupal could not determine the encoding of the database was set to UTF-8'));
-    }
-  }
-
-  /**
-   * Check Binary Output.
-   *
-   * Unserializing does not work on Postgresql 9 when bytea_output is 'hex'.
-   */
-  function checkBinaryOutput() {
-    // PostgreSQL < 9 doesn't support bytea_output, so verify we are running
-    // at least PostgreSQL 9.
-    $database_connection = Database::getConnection();
-    if (version_compare($database_connection->version(), '9') >= 0) {
-      if (!$this->checkBinaryOutputSuccess()) {
-        // First try to alter the database. If it fails, raise an error telling
-        // the user to do it themselves.
-        $connection_options = $database_connection->getConnectionOptions();
-        // It is safe to include the database name directly here, because this
-        // code is only called when a connection to the database is already
-        // established, thus the database name is guaranteed to be a correct
-        // value.
-        $query = "ALTER DATABASE \"" . $connection_options['database'] . "\" SET bytea_output = 'escape';";
-        try {
-          db_query($query);
-        }
-        catch (\Exception $e) {
-          // Ignore possible errors when the user doesn't have the necessary
-          // privileges to ALTER the database.
-        }
-
-        // Close the database connection so that the configuration parameter
-        // is applied to the current connection.
-        db_close();
-
-        // Recheck, if it fails, finally just rely on the end user to do the
-        // right thing.
-        if (!$this->checkBinaryOutputSuccess()) {
-          $replacements = array(
-            '%setting' => 'bytea_output',
-            '%current_value' => 'hex',
-            '%needed_value' => 'escape',
-            '!query' => "<code>" . $query . "</code>",
-          );
-          $this->fail(t("The %setting setting is currently set to '%current_value', but needs to be '%needed_value'. Change this by running the following query: !query", $replacements));
-        }
-      }
-    }
-  }
-
-  /**
-   * Verify that a binary data roundtrip returns the original string.
-   */
-  protected function checkBinaryOutputSuccess() {
-    $bytea_output = db_query("SHOW bytea_output")->fetchField();
-    return ($bytea_output == 'escape');
-  }
-
-  /**
-   * Ensures standard_conforming_strings setting is 'on'.
-   *
-   * When standard_conforming_strings setting is 'on' string literals ('...')
-   * treat backslashes literally, as specified in the SQL standard. This allows
-   * Drupal to convert between bytea, text and varchar columns.
-   */
-  public function checkStandardConformingStrings() {
-    $database_connection = Database::getConnection();
-    if (!$this->checkStandardConformingStringsSuccess()) {
-      // First try to alter the database. If it fails, raise an error telling
-      // the user to do it themselves.
-      $connection_options = $database_connection->getConnectionOptions();
-      // It is safe to include the database name directly here, because this
-      // code is only called when a connection to the database is already
-      // established, thus the database name is guaranteed to be a correct
-      // value.
-      $query = "ALTER DATABASE \"" . $connection_options['database'] . "\" SET standard_conforming_strings = 'on';";
-      try {
-        $database_connection->query($query);
-      }
-      catch (\Exception $e) {
-        // Ignore possible errors when the user doesn't have the necessary
-        // privileges to ALTER the database.
-      }
-
-      // Close the database connection so that the configuration parameter
-      // is applied to the current connection.
-      Database::closeConnection();
-
-      // Recheck, if it fails, finally just rely on the end user to do the
-      // right thing.
-      if (!$this->checkStandardConformingStringsSuccess()) {
-        $replacements = array(
-          '%setting' => 'standard_conforming_strings',
-          '%current_value' => 'off',
-          '%needed_value' => 'on',
-          '!query' => "<code>" . $query . "</code>",
-        );
-        $this->fail(t("The %setting setting is currently set to '%current_value', but needs to be '%needed_value'. Change this by running the following query: !query", $replacements));
-      }
-    }
-  }
-
-  /**
-   * Verifies the standard_conforming_strings setting.
-   */
-  protected function checkStandardConformingStringsSuccess() {
-    $standard_conforming_strings = Database::getConnection()->query("SHOW standard_conforming_strings")->fetchField();
-    return ($standard_conforming_strings == 'on');
-  }
-
-  /**
-   * Make PostgreSQL Drupal friendly.
-   */
-  function initializeDatabase() {
-    // We create some functions using global names instead of prefixing them
-    // like we do with table names. This is so that we don't double up if more
-    // than one instance of Drupal is running on a single database. We therefore
-    // avoid trying to create them again in that case.
-    // At the same time checking for the existence of the function fixes
-    // concurrency issues, when both try to update at the same time.
-    try {
-      // Don't use {} around pg_proc table.
-      if (!db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'rand'")->fetchField()) {
-        db_query('CREATE OR REPLACE FUNCTION "rand"() RETURNS float AS
-          \'SELECT random();\'
-          LANGUAGE \'sql\''
-        );
-      }
-
-      if (!db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'substring_index'")->fetchField()) {
-        db_query('CREATE OR REPLACE FUNCTION "substring_index"(text, text, integer) RETURNS text AS
-          \'SELECT array_to_string((string_to_array($1, $2)) [1:$3], $2);\'
-          LANGUAGE \'sql\''
-        );
-      }
-
-      $this->pass(t('PostgreSQL has initialized itself.'));
-    }
-    catch (\Exception $e) {
-      $this->fail(t('Drupal could not be correctly setup with the existing database due to the following error: @error.', ['@error' => $e->getMessage()]));
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormOptions(array $database) {
-    $form = parent::getFormOptions($database);
-    if (empty($form['advanced_options']['port']['#default_value'])) {
-      $form['advanced_options']['port']['#default_value'] = '5432';
-    }
-    return $form;
-  }
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Merge.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Merge.php
deleted file mode 100644
index ad74c13..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Merge.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
deleted file mode 100644
index 0828d59..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
+++ /dev/null
@@ -1,855 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\pgsql\Schema.
- */
-
-namespace Drupal\Core\Database\Driver\pgsql;
-
-use Drupal\Component\Utility\Unicode;
-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;
-
-/**
- * @addtogroup schemaapi
- * @{
- */
-
-class Schema extends DatabaseSchema {
-
-  /**
-   * A cache of information about blob columns and sequences of tables.
-   *
-   * This is collected by DatabaseConnection_pgsql->queryTableInformation(),
-   * by introspecting the database.
-   *
-   * @see DatabaseConnection_pgsql->queryTableInformation()
-   * @var array
-   */
-  protected $tableInformation = array();
-
-  /**
-   * The maximum allowed length for index, primary key and constraint names.
-   *
-   * Value will usually be set to a 63 chars limit but PostgreSQL allows
-   * to higher this value before compiling, so we need to check for that.
-   *
-   * @var integer
-   */
-  protected $maxIdentifierLength;
-
-  /**
-   * Make sure to limit identifiers according to PostgreSQL compiled in length.
-   *
-   * PostgreSQL allows in standard configuration no longer identifiers than 63
-   * chars for table/relation names, indexes, primary keys, and constraints. So
-   * we map all identifiers that are too long to drupal_base64hash_tag, where
-   * tag is one of:
-   *   - idx for indexes
-   *   - key for constraints
-   *   - pkey for primary keys
-   *
-   * @param $identifiers
-   *   The arguments to build the identifier string
-   * @return
-   *   The index/constraint/pkey identifier
-   */
-  protected function ensureIdentifiersLength($identifier) {
-    $args = func_get_args();
-    $info = $this->getPrefixInfo($identifier);
-    $args[0] = $info['table'];
-    $identifierName = implode('__', $args);
-
-    // Retrieve the max identifier length which is usually 63 characters
-    // but can be altered before PostgreSQL is compiled so we need to check.
-    $this->maxIdentifierLength = $this->connection->query("SHOW max_identifier_length")->fetchField();
-
-    if (strlen($identifierName) > $this->maxIdentifierLength) {
-      $saveIdentifier = '"drupal_' . $this->hashBase64($identifierName) . '_' . $args[2] . '"';
-    }
-    else {
-      $saveIdentifier = $identifierName;
-    }
-    return $saveIdentifier;
-  }
-
-  /**
-   * Fetch the list of blobs and sequences used on a table.
-   *
-   * We introspect the database to collect the information required by insert
-   * and update queries.
-   *
-   * @param $table_name
-   *   The non-prefixed name of the table.
-   * @return
-   *   An object with two member variables:
-   *     - 'blob_fields' that lists all the blob fields in the table.
-   *     - 'sequences' that lists the sequences used in that table.
-   */
-  public function queryTableInformation($table) {
-    // Generate a key to reference this table's information on.
-    $key = $this->connection->prefixTables('{' . $table . '}');
-
-    // Take into account that temporary tables are stored in a different schema.
-    // \Drupal\Core\Database\Connection::generateTemporaryTableName() sets the
-    // 'db_temporary_' prefix to all temporary tables.
-    if (strpos($key, '.') === FALSE && strpos($table, 'db_temporary_') === FALSE) {
-      $key = 'public.' . $key;
-    }
-    else {
-      $schema = $this->connection->query('SELECT nspname FROM pg_namespace WHERE oid = pg_my_temp_schema()')->fetchField();
-      $key = $schema . '.' . $key;
-    }
-
-    if (!isset($this->tableInformation[$key])) {
-      // Split the key into schema and table for querying.
-      list($schema, $table_name) = explode('.', $key);
-      $table_information = (object) array(
-        'blob_fields' => array(),
-        'sequences' => array(),
-      );
-      // Don't use {} around information_schema.columns table.
-      $this->connection->addSavepoint();
-
-      try {
-        // Check if the table information exists in the PostgreSQL metadata.
-        $table_information_exists = (bool) $this->connection->query("SELECT 1 FROM pg_class WHERE relname = :table", array(':table' => $table_name))->fetchField();
-
-        // If the table information does not yet exist in the PostgreSQL
-        // metadata, then return the default table information here, so that it
-        // will not be cached.
-        if (!$table_information_exists) {
-          $this->connection->releaseSavepoint();
-          return $table_information;
-        }
-        else {
-          $result = $this->connection->query("SELECT column_name, data_type, column_default FROM information_schema.columns WHERE table_schema = :schema AND table_name = :table AND (data_type = 'bytea' OR (numeric_precision IS NOT NULL AND column_default LIKE :default))", array(
-            ':schema' => $schema,
-            ':table' => $table_name,
-            ':default' => '%nextval%',
-          ));
-        }
-      }
-      catch (\Exception $e) {
-        $this->connection->rollbackSavepoint();
-        throw $e;
-      }
-      $this->connection->releaseSavepoint();
-
-      foreach ($result as $column) {
-        if ($column->data_type == 'bytea') {
-          $table_information->blob_fields[$column->column_name] = TRUE;
-        }
-        elseif (preg_match("/nextval\('([^']+)'/", $column->column_default, $matches)) {
-          // We must know of any sequences in the table structure to help us
-          // return the last insert id. If there is more than 1 sequences the
-          // first one (index 0 of the sequences array) will be used.
-          $table_information->sequences[] = $matches[1];
-          $table_information->serial_fields[] = $column->column_name;
-        }
-      }
-      $this->tableInformation[$key] = $table_information;
-    }
-    return $this->tableInformation[$key];
-  }
-
-  /**
-   * Resets information about table blobs, sequences and serial fields.
-   *
-   * @param $table
-   *   The non-prefixed name of the table.
-   */
-  protected function resetTableInformation($table) {
-    $key = $this->connection->prefixTables('{' . $table . '}');
-    if (strpos($key, '.') === FALSE) {
-      $key = 'public.' . $key;
-    }
-    unset($this->tableInformation[$key]);
-  }
-
-  /**
-   * Fetch the list of CHECK constraints used on a field.
-   *
-   * We introspect the database to collect the information required by field
-   * alteration.
-   *
-   * @param $table
-   *   The non-prefixed name of the table.
-   * @param $field
-   *   The name of the field.
-   * @return
-   *   An array of all the checks for the field.
-   */
-  public function queryFieldInformation($table, $field) {
-    $prefixInfo = $this->getPrefixInfo($table, TRUE);
-
-    // Split the key into schema and table for querying.
-    $schema = $prefixInfo['schema'];
-    $table_name = $prefixInfo['table'];
-
-    $this->connection->addSavepoint();
-
-    try {
-      $checks = $this->connection->query("SELECT conname FROM pg_class cl INNER JOIN pg_constraint co ON co.conrelid = cl.oid INNER JOIN pg_attribute attr ON attr.attrelid = cl.oid AND attr.attnum = ANY (co.conkey) INNER JOIN pg_namespace ns ON cl.relnamespace = ns.oid WHERE co.contype = 'c' AND ns.nspname = :schema AND cl.relname = :table AND attr.attname = :column", array(
-        ':schema' => $schema,
-        ':table' => $table_name,
-        ':column' => $field,
-      ));
-    }
-    catch (\Exception $e) {
-      $this->connection->rollbackSavepoint();
-      throw $e;
-    }
-
-    $this->connection->releaseSavepoint();
-
-    $field_information = $checks->fetchCol();
-
-    return $field_information;
-  }
-
-  /**
-   * Generate SQL to create a new table from a Drupal schema definition.
-   *
-   * @param $name
-   *   The name of the table to create.
-   * @param $table
-   *   A Schema API table definition array.
-   * @return
-   *   An array of SQL statements to create the table.
-   */
-  protected function createTableSql($name, $table) {
-    $sql_fields = array();
-    foreach ($table['fields'] as $field_name => $field) {
-      $sql_fields[] = $this->createFieldSql($field_name, $this->processField($field));
-    }
-
-    $sql_keys = array();
-    if (isset($table['primary key']) && is_array($table['primary key'])) {
-      $sql_keys[] = 'CONSTRAINT ' . $this->ensureIdentifiersLength($name, '', 'pkey') . ' PRIMARY KEY (' . $this->createPrimaryKeySql($table['primary key']) . ')';
-    }
-    if (isset($table['unique keys']) && is_array($table['unique keys'])) {
-      foreach ($table['unique keys'] as $key_name => $key) {
-        $sql_keys[] = 'CONSTRAINT ' . $this->ensureIdentifiersLength($name, $key_name, 'key') . ' UNIQUE (' . implode(', ', $key) . ')';
-      }
-    }
-
-    $sql = "CREATE TABLE {" . $name . "} (\n\t";
-    $sql .= implode(",\n\t", $sql_fields);
-    if (count($sql_keys) > 0) {
-      $sql .= ",\n\t";
-    }
-    $sql .= implode(",\n\t", $sql_keys);
-    $sql .= "\n)";
-    $statements[] = $sql;
-
-    if (isset($table['indexes']) && is_array($table['indexes'])) {
-      foreach ($table['indexes'] as $key_name => $key) {
-        $statements[] = $this->_createIndexSql($name, $key_name, $key);
-      }
-    }
-
-    // Add table comment.
-    if (!empty($table['description'])) {
-      $statements[] = 'COMMENT ON TABLE {' . $name . '} IS ' . $this->prepareComment($table['description']);
-    }
-
-    // Add column comments.
-    foreach ($table['fields'] as $field_name => $field) {
-      if (!empty($field['description'])) {
-        $statements[] = 'COMMENT ON COLUMN {' . $name . '}.' . $field_name . ' IS ' . $this->prepareComment($field['description']);
-      }
-    }
-
-    return $statements;
-  }
-
-  /**
-   * Create an SQL string for a field to be used in table creation or
-   * alteration.
-   *
-   * Before passing a field out of a schema definition into this
-   * function it has to be processed by _db_process_field().
-   *
-   * @param $name
-   *    Name of the field.
-   * @param $spec
-   *    The field specification, as per the schema data structure format.
-   */
-  protected function createFieldSql($name, $spec) {
-    // The PostgreSQL server converts names into lowercase, unless quoted.
-    $sql = '"' . $name . '" ' . $spec['pgsql_type'];
-
-    if (isset($spec['type']) && $spec['type'] == 'serial') {
-      unset($spec['not null']);
-    }
-
-    if (in_array($spec['pgsql_type'], array('varchar', 'character')) && isset($spec['length'])) {
-      $sql .= '(' . $spec['length'] . ')';
-    }
-    elseif (isset($spec['precision']) && isset($spec['scale'])) {
-      $sql .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
-    }
-
-    if (!empty($spec['unsigned'])) {
-      $sql .= " CHECK ($name >= 0)";
-    }
-
-    if (isset($spec['not null'])) {
-      if ($spec['not null']) {
-        $sql .= ' NOT NULL';
-      }
-      else {
-        $sql .= ' NULL';
-      }
-    }
-    if (array_key_exists('default', $spec)) {
-      $default = $this->escapeDefaultValue($spec['default']);
-      $sql .= " default $default";
-    }
-
-    return $sql;
-  }
-
-  /**
-   * Set database-engine specific properties for a field.
-   *
-   * @param $field
-   *   A field description array, as specified in the schema documentation.
-   */
-  protected function processField($field) {
-    if (!isset($field['size'])) {
-      $field['size'] = 'normal';
-    }
-
-    // Set the correct database-engine specific datatype.
-    // In case one is already provided, force it to lowercase.
-    if (isset($field['pgsql_type'])) {
-      $field['pgsql_type'] = Unicode::strtolower($field['pgsql_type']);
-    }
-    else {
-      $map = $this->getFieldTypeMap();
-      $field['pgsql_type'] = $map[$field['type'] . ':' . $field['size']];
-    }
-
-    if (!empty($field['unsigned'])) {
-      // Unsigned datatypes are not supported in PostgreSQL 9.1. In MySQL,
-      // they are used to ensure a positive number is inserted and it also
-      // doubles the maximum integer size that can be stored in a field.
-      // The PostgreSQL schema in Drupal creates a check constraint
-      // to ensure that a value inserted is >= 0. To provide the extra
-      // integer capacity, here, we bump up the column field size.
-      if (!isset($map)) {
-        $map = $this->getFieldTypeMap();
-      }
-      switch ($field['pgsql_type']) {
-        case 'smallint':
-          $field['pgsql_type'] = $map['int:medium'];
-          break;
-        case 'int' :
-          $field['pgsql_type'] = $map['int:big'];
-          break;
-      }
-    }
-    if (isset($field['type']) && $field['type'] == 'serial') {
-      unset($field['not null']);
-    }
-    return $field;
-  }
-
-  /**
-   * This maps a generic data type in combination with its data size
-   * to the engine-specific data type.
-   */
-  function getFieldTypeMap() {
-    // Put :normal last so it gets preserved by array_flip. This makes
-    // it much easier for modules (such as schema.module) to map
-    // database types back into schema types.
-    // $map does not use drupal_static as its value never changes.
-    static $map = array(
-      'varchar_ascii:normal' => 'varchar',
-
-      'varchar:normal' => 'varchar',
-      'char:normal' => 'character',
-
-      'text:tiny' => 'text',
-      'text:small' => 'text',
-      'text:medium' => 'text',
-      'text:big' => 'text',
-      'text:normal' => 'text',
-
-      'int:tiny' => 'smallint',
-      'int:small' => 'smallint',
-      'int:medium' => 'int',
-      'int:big' => 'bigint',
-      'int:normal' => 'int',
-
-      'float:tiny' => 'real',
-      'float:small' => 'real',
-      'float:medium' => 'real',
-      'float:big' => 'double precision',
-      'float:normal' => 'real',
-
-      'numeric:normal' => 'numeric',
-
-      'blob:big' => 'bytea',
-      'blob:normal' => 'bytea',
-
-      'serial:tiny' => 'serial',
-      'serial:small' => 'serial',
-      'serial:medium' => 'serial',
-      'serial:big' => 'bigserial',
-      'serial:normal' => 'serial',
-      );
-    return $map;
-  }
-
-  protected function _createKeySql($fields) {
-    $return = array();
-    foreach ($fields as $field) {
-      if (is_array($field)) {
-        $return[] = 'substr(' . $field[0] . ', 1, ' . $field[1] . ')';
-      }
-      else {
-        $return[] = '"' . $field . '"';
-      }
-    }
-    return implode(', ', $return);
-  }
-
-  /**
-   * Create the SQL expression for primary keys.
-   *
-   * Postgresql does not support key length. It does support fillfactor, but
-   * that requires a separate database lookup for each column in the key. The
-   * key length defined in the schema is ignored.
-   */
-  protected function createPrimaryKeySql($fields) {
-    $return = array();
-    foreach ($fields as $field) {
-      if (is_array($field)) {
-        $return[] = '"' . $field[0] . '"';
-      }
-      else {
-        $return[] = '"' . $field . '"';
-      }
-    }
-    return implode(', ', $return);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function tableExists($table) {
-    $prefixInfo = $this->getPrefixInfo($table, TRUE);
-
-    return (bool) $this->connection->query("SELECT 1 FROM pg_tables WHERE schemaname = :schema AND tablename = :table", array(':schema' => $prefixInfo['schema'], ':table' => $prefixInfo['table']))->fetchField();
-  }
-
-  function renameTable($table, $new_name) {
-    if (!$this->tableExists($table)) {
-      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 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.
-    $old_full_name = $this->connection->prefixTables('{' . $table . '}');
-    list($old_schema, $old_table_name) = strpos($old_full_name, '.') ? explode('.', $old_full_name) : array('public', $old_full_name);
-
-    // Index names and constraint names are global in PostgreSQL, so we need to
-    // rename them when renaming the table.
-    $indexes = $this->connection->query('SELECT indexname FROM pg_indexes WHERE schemaname = :schema AND tablename = :table', array(':schema' => $old_schema, ':table' => $old_table_name));
-
-    foreach ($indexes as $index) {
-      // Get the index type by suffix, e.g. idx/key/pkey
-      $index_type = substr($index->indexname, strrpos($index->indexname, '_') + 1);
-
-      // If the index is already rewritten by ensureIdentifiersLength() to not
-      // exceed the 63 chars limit of PostgreSQL, we need to take care of that.
-      // Example (drupal_Gk7Su_T1jcBHVuvSPeP22_I3Ni4GrVEgTYlIYnBJkro_idx).
-      if (strpos($index->indexname, 'drupal_') !== FALSE) {
-        preg_match('/^drupal_(.*)_' . preg_quote($index_type) . '/', $index->indexname, $matches);
-        $index_name = $matches[1];
-      }
-      else {
-        // Make sure to remove the suffix from index names, because
-        // $this->ensureIdentifiersLength() will add the suffix again and thus
-        // would result in a wrong index name.
-        preg_match('/^' . preg_quote($old_full_name) . '__(.*)__' . preg_quote($index_type) . '/', $index->indexname, $matches);
-        $index_name = $matches[1];
-      }
-      $this->connection->query('ALTER INDEX "' . $index->indexname . '" RENAME TO ' . $this->ensureIdentifiersLength($new_name, $index_name, $index_type) . '');
-    }
-
-    // Ensure the new table name does not include schema syntax.
-    $prefixInfo = $this->getPrefixInfo($new_name);
-
-    // Rename sequences if there's a serial fields.
-    $info = $this->queryTableInformation($table);
-    if (!empty($info->serial_fields)) {
-      foreach ($info->serial_fields as $field) {
-        $old_sequence = $this->prefixNonTable($table, $field, 'seq');
-        $new_sequence = $this->prefixNonTable($new_name, $field, 'seq');
-        $this->connection->query('ALTER SEQUENCE ' . $old_sequence . ' RENAME TO ' . $new_sequence);
-      }
-    }
-    // Now rename the table.
-    $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO ' . $prefixInfo['table']);
-    $this->resetTableInformation($table);
-  }
-
-  public function dropTable($table) {
-    if (!$this->tableExists($table)) {
-      return FALSE;
-    }
-
-    $this->connection->query('DROP TABLE {' . $table . '}');
-    $this->resetTableInformation($table);
-    return TRUE;
-  }
-
-  public function addField($table, $field, $spec, $new_keys = array()) {
-    if (!$this->tableExists($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 SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
-    }
-
-    $fixnull = FALSE;
-    if (!empty($spec['not null']) && !isset($spec['default'])) {
-      $fixnull = TRUE;
-      $spec['not null'] = FALSE;
-    }
-    $query = 'ALTER TABLE {' . $table . '} ADD COLUMN ';
-    $query .= $this->createFieldSql($field, $this->processField($spec));
-    $this->connection->query($query);
-    if (isset($spec['initial'])) {
-      $this->connection->update($table)
-        ->fields(array($field => $spec['initial']))
-        ->execute();
-    }
-    if ($fixnull) {
-      $this->connection->query("ALTER TABLE {" . $table . "} ALTER $field SET NOT NULL");
-    }
-    if (isset($new_keys)) {
-      $this->_createKeys($table, $new_keys);
-    }
-    // Add column comment.
-    if (!empty($spec['description'])) {
-      $this->connection->query('COMMENT ON COLUMN {' . $table . '}.' . $field . ' IS ' . $this->prepareComment($spec['description']));
-    }
-    $this->resetTableInformation($table);
-  }
-
-  public function dropField($table, $field) {
-    if (!$this->fieldExists($table, $field)) {
-      return FALSE;
-    }
-
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP COLUMN "' . $field . '"');
-    $this->resetTableInformation($table);
-    return TRUE;
-  }
-
-  public function fieldSetDefault($table, $field, $default) {
-    if (!$this->fieldExists($table, $field)) {
-      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
-    }
-
-    $default = $this->escapeDefaultValue($default);
-
-    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" SET DEFAULT ' . $default);
-  }
-
-  public function fieldSetNoDefault($table, $field) {
-    if (!$this->fieldExists($table, $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');
-  }
-
-  public function indexExists($table, $name) {
-    // Details http://www.postgresql.org/docs/9.1/interactive/view-pg-indexes.html
-    $index_name = $this->ensureIdentifiersLength($table, $name, 'idx');
-    // Remove leading and trailing quotes because the index name is in a WHERE
-    // clause and not used as an identifier.
-    $index_name = str_replace('"', '', $index_name);
-    return (bool) $this->connection->query("SELECT 1 FROM pg_indexes WHERE indexname = '$index_name'")->fetchField();
-  }
-
-  /**
-   * Helper function: check if a constraint (PK, FK, UK) exists.
-   *
-   * @param string $table
-   *   The name of the table.
-   * @param string $name
-   *   The name of the constraint (typically 'pkey' or '[constraint]__key').
-   *
-   * @return bool
-   *   TRUE if the constraint exists, FALSE otherwise.
-   */
-  public function constraintExists($table, $name) {
-    // ::ensureIdentifiersLength() expects three parameters, although not
-    // explicitly stated in its signature, thus we split our constraint name in
-    // a proper name and a suffix.
-    if ($name == 'pkey') {
-      $suffix = $name;
-      $name = '';
-    }
-    else {
-      $pos = strrpos($name, '__');
-      $suffix = substr($name, $pos + 2);
-      $name = substr($name, 0, $pos);
-    }
-    $constraint_name = $this->ensureIdentifiersLength($table, $name, $suffix);
-    // Remove leading and trailing quotes because the index name is in a WHERE
-    // clause and not used as an identifier.
-    $constraint_name = str_replace('"', '', $constraint_name);
-    return (bool) $this->connection->query("SELECT 1 FROM pg_constraint WHERE conname = '$constraint_name'")->fetchField();
-  }
-
-  public function addPrimaryKey($table, $fields) {
-    if (!$this->tableExists($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 SchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
-    }
-
-    $this->connection->query('ALTER TABLE {' . $table . '} ADD CONSTRAINT ' . $this->ensureIdentifiersLength($table, '', 'pkey') . ' PRIMARY KEY (' . $this->createPrimaryKeySql($fields) . ')');
-    $this->resetTableInformation($table);
-  }
-
-  public function dropPrimaryKey($table) {
-    if (!$this->constraintExists($table, 'pkey')) {
-      return FALSE;
-    }
-
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $this->ensureIdentifiersLength($table, '', 'pkey'));
-    $this->resetTableInformation($table);
-    return TRUE;
-  }
-
-  function addUniqueKey($table, $name, $fields) {
-    if (!$this->tableExists($table)) {
-      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 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->ensureIdentifiersLength($table, $name, 'key') . ' UNIQUE (' . implode(',', $fields) . ')');
-    $this->resetTableInformation($table);
-  }
-
-  public function dropUniqueKey($table, $name) {
-    if (!$this->constraintExists($table, $name . '__key')) {
-      return FALSE;
-    }
-
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $this->ensureIdentifiersLength($table, $name, 'key'));
-    $this->resetTableInformation($table);
-    return TRUE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function addIndex($table, $name, $fields, array $spec) {
-    if (!$this->tableExists($table)) {
-      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 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));
-    $this->resetTableInformation($table);
-  }
-
-  public function dropIndex($table, $name) {
-    if (!$this->indexExists($table, $name)) {
-      return FALSE;
-    }
-
-    $this->connection->query('DROP INDEX ' . $this->ensureIdentifiersLength($table, $name, 'idx'));
-    $this->resetTableInformation($table);
-    return TRUE;
-  }
-
-  public function changeField($table, $field, $field_new, $spec, $new_keys = array()) {
-    if (!$this->fieldExists($table, $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 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);
-
-    // Type 'serial' is known to PostgreSQL, but only during table creation,
-    // not when altering. Because of that, we create it here as an 'int'. After
-    // we create it we manually re-apply the sequence.
-    if (in_array($spec['pgsql_type'], array('serial', 'bigserial'))) {
-      $field_def = 'int';
-    }
-    else {
-      $field_def = $spec['pgsql_type'];
-    }
-
-    if (in_array($spec['pgsql_type'], array('varchar', 'character', 'text')) && isset($spec['length'])) {
-      $field_def .= '(' . $spec['length'] . ')';
-    }
-    elseif (isset($spec['precision']) && isset($spec['scale'])) {
-      $field_def .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
-    }
-
-    // Remove old check constraints.
-    $field_info = $this->queryFieldInformation($table, $field);
-
-    foreach ($field_info as $check) {
-      $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT "' . $check . '"');
-    }
-
-    // Remove old default.
-    $this->fieldSetNoDefault($table, $field);
-
-    // Convert field type.
-    // Usually, we do this via a simple typecast 'USING fieldname::type'. But
-    // the typecast does not work for conversions to bytea.
-    // @see http://www.postgresql.org/docs/current/static/datatype-binary.html
-    $table_information = $this->queryTableInformation($table);
-    $is_bytea = !empty($table_information->blob_fields[$field]);
-    if ($spec['pgsql_type'] != 'bytea') {
-      if ($is_bytea) {
-        $this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" TYPE ' . $field_def . ' USING convert_from("' . $field . '"' . ", 'UTF8')");
-      }
-      else {
-        $this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" TYPE ' . $field_def . ' USING "' . $field . '"::' . $field_def);
-      }
-    }
-    else {
-      // Do not attempt to convert a field that is bytea already.
-      if (!$is_bytea) {
-        // Convert to a bytea type by using the SQL replace() function to
-        // convert any single backslashes in the field content to double
-        // backslashes ('\' to '\\').
-        $this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" TYPE ' . $field_def . ' USING decode(replace("' . $field . '"' . ", E'\\\\', E'\\\\\\\\'), 'escape');");
-      }
-    }
-
-    if (isset($spec['not null'])) {
-      if ($spec['not null']) {
-        $nullaction = 'SET NOT NULL';
-      }
-      else {
-        $nullaction = 'DROP NOT NULL';
-      }
-      $this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" ' . $nullaction);
-    }
-
-    if (in_array($spec['pgsql_type'], array('serial', 'bigserial'))) {
-      // Type "serial" is known to PostgreSQL, but *only* during table creation,
-      // not when altering. Because of that, the sequence needs to be created
-      // and initialized by hand.
-      $seq = "{" . $table . "}_" . $field_new . "_seq";
-      $this->connection->query("CREATE SEQUENCE " . $seq);
-      // Set sequence to maximal field value to not conflict with existing
-      // entries.
-      $this->connection->query("SELECT setval('" . $seq . "', MAX(\"" . $field . '")) FROM {' . $table . "}");
-      $this->connection->query('ALTER TABLE {' . $table . '} ALTER ' . $field . ' SET DEFAULT nextval(' . $this->connection->quote($seq) . ')');
-    }
-
-    // Rename the column if necessary.
-    if ($field != $field_new) {
-      $this->connection->query('ALTER TABLE {' . $table . '} RENAME "' . $field . '" TO "' . $field_new . '"');
-    }
-
-    // Add unsigned check if necessary.
-    if (!empty($spec['unsigned'])) {
-      $this->connection->query('ALTER TABLE {' . $table . '} ADD CHECK ("' . $field_new . '" >= 0)');
-    }
-
-    // Add default if necessary.
-    if (isset($spec['default'])) {
-      $this->fieldSetDefault($table, $field_new, $spec['default']);
-    }
-
-    // Change description if necessary.
-    if (!empty($spec['description'])) {
-      $this->connection->query('COMMENT ON COLUMN {' . $table . '}."' . $field_new . '" IS ' . $this->prepareComment($spec['description']));
-    }
-
-    if (isset($new_keys)) {
-      $this->_createKeys($table, $new_keys);
-    }
-    $this->resetTableInformation($table);
-  }
-
-  protected function _createIndexSql($table, $name, $fields) {
-    $query = 'CREATE INDEX ' . $this->ensureIdentifiersLength($table, $name, 'idx') . ' ON {' . $table . '} (';
-    $query .= $this->_createKeySql($fields) . ')';
-    return $query;
-  }
-
-  protected function _createKeys($table, $new_keys) {
-    if (isset($new_keys['primary key'])) {
-      $this->addPrimaryKey($table, $new_keys['primary key']);
-    }
-    if (isset($new_keys['unique keys'])) {
-      foreach ($new_keys['unique keys'] as $name => $fields) {
-        $this->addUniqueKey($table, $name, $fields);
-      }
-    }
-    if (isset($new_keys['indexes'])) {
-      foreach ($new_keys['indexes'] as $name => $fields) {
-        // Even though $new_keys is not a full schema it still has 'indexes' and
-        // so is a partial schema. Technically addIndex() doesn't do anything
-        // with it so passing an empty array would work as well.
-        $this->addIndex($table, $name, $fields, $new_keys);
-      }
-    }
-  }
-
-  /**
-   * Retrieve a table or column comment.
-   */
-  public function getComment($table, $column = NULL) {
-    $info = $this->getPrefixInfo($table);
-    // Don't use {} around pg_class, pg_attribute tables.
-    if (isset($column)) {
-      return $this->connection->query('SELECT col_description(oid, attnum) FROM pg_class, pg_attribute WHERE attrelid = oid AND relname = ? AND attname = ?', array($info['table'], $column))->fetchField();
-    }
-    else {
-      return $this->connection->query('SELECT obj_description(oid, ?) FROM pg_class WHERE relname = ?', array('pg_class', $info['table']))->fetchField();
-    }
-  }
-
-  /**
-   * Calculates a base-64 encoded, PostgreSQL-safe sha-256 hash per PostgreSQL
-   * documentation: 4.1. Lexical Structure.
-   *
-   * @param $data
-   *   String to be hashed.
-   * @return string
-   *   A base-64 encoded sha-256 hash, with + and / replaced with _ and any =
-   *   padding characters removed.
-   */
-  protected function hashBase64($data) {
-    $hash = base64_encode(hash('sha256', $data, TRUE));
-    // Modify the hash so it's safe to use in PostgreSQL identifiers.
-    return strtr($hash, array('+' => '_', '/' => '_', '=' => ''));
-  }
-}
-
-/**
- * @} End of "addtogroup schemaapi".
- */
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
deleted file mode 100644
index 0b58c67..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
+++ /dev/null
@@ -1,161 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\pgsql\Select.
- */
-
-namespace Drupal\Core\Database\Driver\pgsql;
-
-use Drupal\Core\Database\Query\Select as QuerySelect;
-
-/**
- * @addtogroup database
- * @{
- */
-
-class Select extends QuerySelect {
-
-  public function orderRandom() {
-    $alias = $this->addExpression('RANDOM()', 'random_field');
-    $this->orderBy($alias);
-    return $this;
-  }
-
-  /**
-   * Overrides SelectQuery::orderBy().
-   *
-   * PostgreSQL adheres strictly to the SQL-92 standard and requires that when
-   * using DISTINCT or GROUP BY conditions, fields and expressions that are
-   * ordered on also need to be selected. This is a best effort implementation
-   * to handle the cases that can be automated by adding the field if it is not
-   * yet selected.
-   *
-   * @code
-   *   $query = db_select('example', 'e');
-   *   $query->join('example_revision', 'er', 'e.vid = er.vid');
-   *   $query
-   *     ->distinct()
-   *     ->fields('e')
-   *     ->orderBy('timestamp');
-   * @endcode
-   *
-   * In this query, it is not possible (without relying on the schema) to know
-   * whether timestamp belongs to example_revision and needs to be added or
-   * belongs to node and is already selected. Queries like this will need to be
-   * corrected in the original query by adding an explicit call to
-   * SelectQuery::addField() or SelectQuery::fields().
-   *
-   * Since this has a small performance impact, both by the additional
-   * processing in this function and in the database that needs to return the
-   * additional fields, this is done as an override instead of implementing it
-   * directly in SelectQuery::orderBy().
-   */
-  public function orderBy($field, $direction = 'ASC') {
-    // Only allow ASC and DESC, default to ASC.
-    // Emulate MySQL default behavior to sort NULL values first for ascending,
-    // and last for descending.
-    // @see http://www.postgresql.org/docs/9.3/static/queries-order.html
-    $direction = strtoupper($direction) == 'DESC' ? 'DESC NULLS LAST' : 'ASC NULLS FIRST';
-    $this->order[$field] = $direction;
-
-    if ($this->hasTag('entity_query')) {
-      return $this;
-    }
-
-    // If there is a table alias specified, split it up.
-    if (strpos($field, '.') !== FALSE) {
-      list($table, $table_field) = explode('.', $field);
-    }
-    // Figure out if the field has already been added.
-    foreach ($this->fields as $existing_field) {
-      if (!empty($table)) {
-        // If table alias is given, check if field and table exists.
-        if ($existing_field['table'] == $table && $existing_field['field'] == $table_field) {
-          return $this;
-        }
-      }
-      else {
-        // If there is no table, simply check if the field exists as a field or
-        // an aliased field.
-        if ($existing_field['alias'] == $field) {
-          return $this;
-        }
-      }
-    }
-
-    // Also check expression aliases.
-    foreach ($this->expressions as $expression) {
-      if ($expression['alias'] == $this->connection->escapeAlias($field)) {
-        return $this;
-      }
-    }
-
-    // If a table loads all fields, it can not be added again. It would
-    // result in an ambiguous alias error because that field would be loaded
-    // twice: Once through table_alias.* and once directly. If the field
-    // actually belongs to a different table, it must be added manually.
-    foreach ($this->tables as $table) {
-      if (!empty($table['all_fields'])) {
-        return $this;
-      }
-    }
-
-    // If $field contains an characters which are not allowed in a field name
-    // it is considered an expression, these can't be handled automatically
-    // either.
-    if ($this->connection->escapeField($field) != $field) {
-      return $this;
-    }
-
-    // This is a case that can be handled automatically, add the field.
-    $this->addField(NULL, $field);
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function addExpression($expression, $alias = NULL, $arguments = array()) {
-    if (empty($alias)) {
-      $alias = 'expression';
-    }
-
-    // This implements counting in the same manner as the parent method.
-    $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' => $this->connection->escapeAlias($alias_candidate),
-      'arguments' => $arguments,
-    );
-
-    return $alias;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function execute() {
-    $this->connection->addSavepoint();
-    try {
-      $result = parent::execute();
-    }
-    catch (\Exception $e) {
-      $this->connection->rollbackSavepoint();
-      throw $e;
-    }
-    $this->connection->releaseSavepoint();
-
-    return $result;
-  }
-}
-
-/**
- * @} End of "addtogroup database".
- */
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Transaction.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Transaction.php
deleted file mode 100644
index 682c53c..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Transaction.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\pgsql\Transaction.
- */
-
-namespace Drupal\Core\Database\Driver\pgsql;
-
-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
deleted file mode 100644
index c0ad989..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Truncate.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\pgsql\Truncate.
- */
-
-namespace Drupal\Core\Database\Driver\pgsql;
-
-use Drupal\Core\Database\Query\Truncate as QueryTruncate;
-
-class Truncate extends QueryTruncate {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function execute() {
-    $this->connection->addSavepoint();
-    try {
-      $result = parent::execute();
-    }
-    catch (\Exception $e) {
-      $this->connection->rollbackSavepoint();
-      throw $e;
-    }
-    $this->connection->releaseSavepoint();
-
-    return $result;
-  }
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php
deleted file mode 100644
index 5d4171d..0000000
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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 Drupal\Core\Database\Query\SelectInterface;
-
-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;
-    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]);
-        }
-      }
-      if ($data['expression'] instanceof SelectInterface) {
-        $data['expression']->compile($this->connection, $this);
-        $select_query_arguments = $data['expression']->arguments();
-        foreach ($select_query_arguments as $placeholder => $argument) {
-          $stmt->bindParam($placeholder, $select_query_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;
-    $options['return'] = Database::RETURN_AFFECTED;
-
-    $this->connection->addSavepoint();
-    try {
-      $result = $this->connection->query($stmt, array(), $options);
-      $this->connection->releaseSavepoint();
-      return $result;
-    }
-    catch (\Exception $e) {
-      $this->connection->rollbackSavepoint();
-      throw $e;
-    }
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
deleted file mode 100644
index e1eb459..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
+++ /dev/null
@@ -1,418 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\sqlite\Connection.
- */
-
-namespace Drupal\Core\Database\Driver\sqlite;
-
-use Drupal\Core\Database\Database;
-use Drupal\Core\Database\DatabaseNotFoundException;
-use Drupal\Core\Database\Connection as DatabaseConnection;
-
-/**
- * Specific SQLite implementation of DatabaseConnection.
- */
-class Connection extends DatabaseConnection {
-
-  /**
-   * Error code for "Unable to open database file" error.
-   */
-  const DATABASE_NOT_FOUND = 14;
-
-  /**
-   * Whether or not the active transaction (if any) will be rolled back.
-   *
-   * @var bool
-   */
-  protected $willRollback;
-
-  /**
-   * 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();
-
-  /**
-   * 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 Schema needs to
-   * access it. However, it should not be manually set.
-   *
-   * @var bool
-   */
-  var $tableDropped = FALSE;
-
-  /**
-   * Constructs a \Drupal\Core\Database\Driver\sqlite\Connection object.
-   */
-  public function __construct(\PDO $connection, array $connection_options) {
-    // We don't need a specific PDOStatement class here, we simulate it in
-    // static::prepare().
-    $this->statementClass = NULL;
-
-    parent::__construct($connection, $connection_options);
-
-    // This driver defaults to transaction support, except if explicitly passed FALSE.
-    $this->transactionSupport = $this->transactionalDDLSupport = !isset($connection_options['transactions']) || $connection_options['transactions'] !== FALSE;
-
-    $this->connectionOptions = $connection_options;
-
-    // Attach one database for each registered prefix.
-    $prefixes = $this->prefixes;
-    foreach ($prefixes as &$prefix) {
-      // Empty prefix means query the main database -- no need to attach anything.
-      if (!empty($prefix)) {
-        // Only attach the database once.
-        if (!isset($this->attachedDatabases[$prefix])) {
-          $this->attachedDatabases[$prefix] = $prefix;
-          if ($connection_options['database'] === ':memory:') {
-            // In memory database use ':memory:' as database name. According to
-            // http://www.sqlite.org/inmemorydb.html it will open a unique
-            // database so attaching it twice is not a problem.
-            $this->query('ATTACH DATABASE :database AS :prefix', array(':database' => $connection_options['database'], ':prefix' => $prefix));
-          }
-          else {
-            $this->query('ATTACH DATABASE :database AS :prefix', array(':database' => $connection_options['database'] . '-' . $prefix, ':prefix' => $prefix));
-          }
-        }
-
-        // Add a ., so queries become prefix.table, which is proper syntax for
-        // querying an attached database.
-        $prefix .= '.';
-      }
-    }
-    // Regenerate the prefixes replacement table.
-    $this->setPrefix($prefixes);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function open(array &$connection_options = array()) {
-    // Allow PDO options to be overridden.
-    $connection_options += array(
-      'pdo' => array(),
-    );
-    $connection_options['pdo'] += array(
-      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
-      // Convert numeric values to strings when fetching.
-      \PDO::ATTR_STRINGIFY_FETCHES => TRUE,
-    );
-    $pdo = new \PDO('sqlite:' . $connection_options['database'], '', '', $connection_options['pdo']);
-
-    // Create functions needed by SQLite.
-    $pdo->sqliteCreateFunction('if', array(__CLASS__, 'sqlFunctionIf'));
-    $pdo->sqliteCreateFunction('greatest', array(__CLASS__, 'sqlFunctionGreatest'));
-    $pdo->sqliteCreateFunction('pow', 'pow', 2);
-    $pdo->sqliteCreateFunction('exp', 'exp', 1);
-    $pdo->sqliteCreateFunction('length', 'strlen', 1);
-    $pdo->sqliteCreateFunction('md5', 'md5', 1);
-    $pdo->sqliteCreateFunction('concat', array(__CLASS__, 'sqlFunctionConcat'));
-    $pdo->sqliteCreateFunction('concat_ws', array(__CLASS__, 'sqlFunctionConcatWs'));
-    $pdo->sqliteCreateFunction('substring', array(__CLASS__, 'sqlFunctionSubstring'), 3);
-    $pdo->sqliteCreateFunction('substring_index', array(__CLASS__, 'sqlFunctionSubstringIndex'), 3);
-    $pdo->sqliteCreateFunction('rand', array(__CLASS__, 'sqlFunctionRand'));
-    $pdo->sqliteCreateFunction('regexp', array(__CLASS__, 'sqlFunctionRegexp'));
-
-    // SQLite does not support the LIKE BINARY operator, so we overload the
-    // non-standard GLOB operator for case-sensitive matching. Another option
-    // would have been to override another non-standard operator, MATCH, but
-    // that does not support the NOT keyword prefix.
-    $pdo->sqliteCreateFunction('glob', array(__CLASS__, 'sqlFunctionLikeBinary'));
-
-    // Create a user-space case-insensitive collation with UTF-8 support.
-    $pdo->sqliteCreateCollation('NOCASE_UTF8', array('Drupal\Component\Utility\Unicode', 'strcasecmp'));
-
-    // Execute sqlite init_commands.
-    if (isset($connection_options['init_commands'])) {
-      $pdo->exec(implode('; ', $connection_options['init_commands']));
-    }
-
-    return $pdo;
-  }
-
-
-  /**
-   * Destructor for the SQLite connection.
-   *
-   * We prune empty databases on destruct, but only if tables have been
-   * dropped. This is especially needed when running the test suite, which
-   * creates and destroy databases several times in a row.
-   */
-  public function __destruct() {
-    if ($this->tableDropped && !empty($this->attachedDatabases)) {
-      foreach ($this->attachedDatabases as $prefix) {
-        // Check if the database is now empty, ignore the internal SQLite tables.
-        try {
-          $count = $this->query('SELECT COUNT(*) FROM ' . $prefix . '.sqlite_master WHERE type = :type AND name NOT LIKE :pattern', array(':type' => 'table', ':pattern' => 'sqlite_%'))->fetchField();
-
-          // We can prune the database file if it doesn't have any tables.
-          if ($count == 0) {
-            // Detaching the database fails at this point, but no other queries
-            // are executed after the connection is destructed so we can simply
-            // remove the database file.
-            unlink($this->connectionOptions['database'] . '-' . $prefix);
-          }
-        }
-        catch (\Exception $e) {
-          // Ignore the exception and continue. There is nothing we can do here
-          // to report the error or fail safe.
-        }
-      }
-    }
-  }
-
-  /**
-   * Gets all the attached databases.
-   *
-   * @return array
-   *   An array of attached database names.
-   *
-   * @see \Drupal\Core\Database\Driver\sqlite\Connection::__construct()
-   */
-  public function getAttachedDatabases() {
-    return $this->attachedDatabases;
-  }
-
-  /**
-   * SQLite compatibility implementation for the IF() SQL function.
-   */
-  public static function sqlFunctionIf($condition, $expr1, $expr2 = NULL) {
-    return $condition ? $expr1 : $expr2;
-  }
-
-  /**
-   * SQLite compatibility implementation for the GREATEST() SQL function.
-   */
-  public static function sqlFunctionGreatest() {
-    $args = func_get_args();
-    foreach ($args as $v) {
-      if (!isset($v)) {
-        unset($args);
-      }
-    }
-    if (count($args)) {
-      return max($args);
-    }
-    else {
-      return NULL;
-    }
-  }
-
-  /**
-   * SQLite compatibility implementation for the CONCAT() SQL function.
-   */
-  public static function sqlFunctionConcat() {
-    $args = func_get_args();
-    return implode('', $args);
-  }
-
-  /**
-   * SQLite compatibility implementation for the CONCAT_WS() SQL function.
-   *
-   * @see http://dev.mysql.com/doc/refman/5.6/en/string-functions.html#function_concat-ws
-   */
-  public static function sqlFunctionConcatWs() {
-    $args = func_get_args();
-    $separator = array_shift($args);
-    // If the separator is NULL, the result is NULL.
-    if ($separator === FALSE || is_null($separator)) {
-      return NULL;
-    }
-    // Skip any NULL values after the separator argument.
-    $args = array_filter($args, function ($value) {
-      return !is_null($value);
-    });
-    return implode($separator, $args);
-  }
-
-  /**
-   * SQLite compatibility implementation for the SUBSTRING() SQL function.
-   */
-  public static function sqlFunctionSubstring($string, $from, $length) {
-    return substr($string, $from - 1, $length);
-  }
-
-  /**
-   * SQLite compatibility implementation for the SUBSTRING_INDEX() SQL function.
-   */
-  public static function sqlFunctionSubstringIndex($string, $delimiter, $count) {
-    // If string is empty, simply return an empty string.
-    if (empty($string)) {
-      return '';
-    }
-    $end = 0;
-    for ($i = 0; $i < $count; $i++) {
-      $end = strpos($string, $delimiter, $end + 1);
-      if ($end === FALSE) {
-        $end = strlen($string);
-      }
-    }
-    return substr($string, 0, $end);
-  }
-
-  /**
-   * SQLite compatibility implementation for the RAND() SQL function.
-   */
-  public static function sqlFunctionRand($seed = NULL) {
-    if (isset($seed)) {
-      mt_srand($seed);
-    }
-    return mt_rand() / mt_getrandmax();
-  }
-
-  /**
-   * SQLite compatibility implementation for the REGEXP SQL operator.
-   *
-   * The REGEXP operator is natively known, but not implemented by default.
-   *
-   * @see http://www.sqlite.org/lang_expr.html#regexp
-   */
-  public static function sqlFunctionRegexp($pattern, $subject) {
-    // preg_quote() cannot be used here, since $pattern may contain reserved
-    // regular expression characters already (such as ^, $, etc). Therefore,
-    // use a rare character as PCRE delimiter.
-    $pattern = '#' . addcslashes($pattern, '#') . '#i';
-    return preg_match($pattern, $subject);
-  }
-
-  /**
-   * SQLite compatibility implementation for the LIKE BINARY SQL operator.
-   *
-   * SQLite supports case-sensitive LIKE operations through the
-   * 'case_sensitive_like' PRAGMA statement, but only for ASCII characters, so
-   * we have to provide our own implementation with UTF-8 support.
-   *
-   * @see https://sqlite.org/pragma.html#pragma_case_sensitive_like
-   * @see https://sqlite.org/lang_expr.html#like
-   */
-  public static function sqlFunctionLikeBinary($pattern, $subject) {
-    // Replace the SQL LIKE wildcard meta-characters with the equivalent regular
-    // expression meta-characters and escape the delimiter that will be used for
-    // matching.
-    $pattern = str_replace(array('%', '_'), array('.*?', '.'), preg_quote($pattern, '/'));
-    return preg_match('/^' . $pattern . '$/', $subject);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function prepare($statement, array $driver_options = array()) {
-    return new Statement($this->connection, $this, $statement, $driver_options);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function handleQueryException(\PDOException $e, $query, array $args = array(), $options = array()) {
-    // The database schema might be changed by another process in between the
-    // time that the statement was prepared and the time the statement was run
-    // (e.g. usually happens when running tests). In this case, we need to
-    // re-run the query.
-    // @see http://www.sqlite.org/faq.html#q15
-    // @see http://www.sqlite.org/rescode.html#schema
-    if (!empty($e->errorInfo[1]) && $e->errorInfo[1] === 17) {
-      return $this->query($query, $args, $options);
-    }
-
-    parent::handleQueryException($e, $query, $args, $options);
-  }
-
-  public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
-    return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options);
-  }
-
-  public function queryTemporary($query, array $args = array(), array $options = array()) {
-    // Generate a new temporary table name and protect it from prefixing.
-    // SQLite requires that temporary tables to be non-qualified.
-    $tablename = $this->generateTemporaryTableName();
-    $prefixes = $this->prefixes;
-    $prefixes[$tablename] = '';
-    $this->setPrefix($prefixes);
-
-    $this->query('CREATE TEMPORARY TABLE ' . $tablename . ' AS ' . $query, $args, $options);
-    return $tablename;
-  }
-
-  public function driver() {
-    return 'sqlite';
-  }
-
-  public function databaseType() {
-    return 'sqlite';
-  }
-
-  /**
-   * Overrides \Drupal\Core\Database\Connection::createDatabase().
-   *
-   * @param string $database
-   *   The name of the database to create.
-   *
-   * @throws \Drupal\Core\Database\DatabaseNotFoundException
-   */
-  public function createDatabase($database) {
-    // Verify the database is writable.
-    $db_directory = new \SplFileInfo(dirname($database));
-    if (!$db_directory->isDir() && !drupal_mkdir($db_directory->getPathName(), 0755, TRUE)) {
-      throw new DatabaseNotFoundException('Unable to create database directory ' . $db_directory->getPathName());
-    }
-  }
-
-  public function mapConditionOperator($operator) {
-    // We don't want to override any of the defaults.
-    static $specials = array(
-      'LIKE' => array('postfix' => " ESCAPE '\\'"),
-      'NOT LIKE' => array('postfix' => " ESCAPE '\\'"),
-      'LIKE BINARY' => array('postfix' => " ESCAPE '\\'", 'operator' => 'GLOB'),
-      'NOT LIKE BINARY' => array('postfix' => " ESCAPE '\\'", 'operator' => 'NOT GLOB'),
-    );
-    return isset($specials[$operator]) ? $specials[$operator] : NULL;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function prepareQuery($query) {
-    return $this->prepare($this->prefixTables($query));
-  }
-
-  public function nextId($existing_id = 0) {
-    $this->startTransaction();
-    // We can safely use literal queries here instead of the slower query
-    // builder because if a given database breaks here then it can simply
-    // override nextId. However, this is unlikely as we deal with short strings
-    // and integers and no known databases require special handling for those
-    // simple cases. If another transaction wants to write the same row, it will
-    // wait until this transaction commits. Also, the return value needs to be
-    // set to RETURN_AFFECTED as if it were a real update() query otherwise it
-    // is not possible to get the row count properly.
-    $affected = $this->query('UPDATE {sequences} SET value = GREATEST(value, :existing_id) + 1', array(
-      ':existing_id' => $existing_id,
-    ), array('return' => Database::RETURN_AFFECTED));
-    if (!$affected) {
-      $this->query('INSERT INTO {sequences} (value) VALUES (:existing_id + 1)', array(
-        ':existing_id' => $existing_id,
-      ));
-    }
-    // The transaction gets committed when the transaction object gets destroyed
-    // because it gets out of scope.
-    return $this->query('SELECT value FROM {sequences}')->fetchField();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFullQualifiedTableName($table) {
-    $prefix = $this->tablePrefix($table);
-
-    // Don't include the SQLite database file name as part of the table name.
-    return $prefix . $table;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Delete.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Delete.php
deleted file mode 100644
index a6a07ce..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Delete.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\sqlite\Delete.
- */
-
-namespace Drupal\Core\Database\Driver\sqlite;
-
-use Drupal\Core\Database\Query\Delete as QueryDelete;
-
-/**
- * SQLite specific implementation of \Drupal\Core\Database\Query\Delete.
- */
-class Delete extends QueryDelete { }
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Insert.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Insert.php
deleted file mode 100644
index 0e940e7..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Insert.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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) || !empty($this->fromQuery)) {
-      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();
-    if (!empty($this->insertFields)) {
-      $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)) {
-      $insert_fields_string = $this->insertFields ? ' (' . implode(', ', $this->insertFields) . ') ' : ' ';
-      return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery;
-    }
-
-    return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') VALUES (' . implode(', ', $placeholders) . ')';
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
deleted file mode 100644
index 6f18a8f..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\sqlite\Install\Tasks.
- */
-
-namespace Drupal\Core\Database\Driver\sqlite\Install;
-
-use Drupal\Core\Database\Database;
-use Drupal\Core\Database\Driver\sqlite\Connection;
-use Drupal\Core\Database\DatabaseNotFoundException;
-use Drupal\Core\Database\Install\Tasks as InstallTasks;
-
-/**
- * Specifies installation tasks for SQLite databases.
- */
-class Tasks extends InstallTasks {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected $pdoDriver = 'sqlite';
-
-  /**
-   * {@inheritdoc}
-   */
-  public function name() {
-    return t('SQLite');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function minimumVersion() {
-    return '3.6.8';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormOptions(array $database) {
-    $form = parent::getFormOptions($database);
-
-    // Remove the options that only apply to client/server style databases.
-    unset($form['username'], $form['password'], $form['advanced_options']['host'], $form['advanced_options']['port']);
-
-    // Make the text more accurate for SQLite.
-    $form['database']['#title'] = t('Database file');
-    $form['database']['#description'] = t('The absolute path to the file where @drupal data will be stored. This must be writable by the web server and should exist outside of the web root.', array('@drupal' => drupal_install_profile_distribution_name()));
-    $default_database = \Drupal::service('site.path') . '/files/.ht.sqlite';
-    $form['database']['#default_value'] = empty($database['database']) ? $default_database : $database['database'];
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  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) {
-      // Attempt to create the database if it is not found.
-      if ($e->getCode() == Connection::DATABASE_NOT_FOUND) {
-        // Remove the database string from connection info.
-        $connection_info = Database::getConnectionInfo();
-        $database = $connection_info['default']['database'];
-
-        // We cannot use file_directory_temp() here because we haven't yet
-        // successfully connected to the database.
-        $connection_info['default']['database'] = drupal_tempnam(sys_get_temp_dir(), 'sqlite');
-
-        // In order to change the Database::$databaseInfo array, need to remove
-        // the active connection, then re-add it with the new info.
-        Database::removeConnection('default');
-        Database::addConnectionInfo('default', 'default', $connection_info['default']);
-
-        try {
-          Database::getConnection()->createDatabase($database);
-          Database::closeConnection();
-
-          // Now, restore the database config.
-          Database::removeConnection('default');
-          $connection_info['default']['database'] = $database;
-          Database::addConnectionInfo('default', 'default', $connection_info['default']);
-
-          // Check the database connection.
-          Database::getConnection();
-          $this->pass('Drupal can CONNECT to the database ok.');
-        }
-        catch (DatabaseNotFoundException $e) {
-          // Still no dice; probably a permission issue. Raise the error to the
-          // installer.
-          $this->fail(t('Database %database not found. The server reports the following message when attempting to create the database: %error.', array('%database' => $database, '%error' => $e->getMessage())));
-        }
-      }
-      else {
-        // Database connection failed for some other reason than the database
-        // not existing.
-        $this->fail(t('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;
-  }
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Merge.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Merge.php
deleted file mode 100644
index 2acea07..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Merge.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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/lib/Drupal/Core/Database/Driver/sqlite/Schema.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
deleted file mode 100644
index 404cbb2..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
+++ /dev/null
@@ -1,726 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\sqlite\Schema.
- */
-
-namespace Drupal\Core\Database\Driver\sqlite;
-
-use Drupal\Component\Utility\Unicode;
-use Drupal\Core\Database\SchemaObjectExistsException;
-use Drupal\Core\Database\SchemaObjectDoesNotExistException;
-use Drupal\Core\Database\Schema as DatabaseSchema;
-
-/**
- * @ingroup schemaapi
- * @{
- */
-
-class Schema extends DatabaseSchema {
-
-  /**
-   * Override DatabaseSchema::$defaultSchema
-   */
-  protected $defaultSchema = 'main';
-
-  public function tableExists($table) {
-    $info = $this->getPrefixInfo($table);
-
-    // Don't use {} around sqlite_master table.
-    return (bool) $this->connection->query('SELECT 1 FROM ' . $info['schema'] . '.sqlite_master WHERE type = :type AND name = :name', array(':type' => 'table', ':name' => $info['table']))->fetchField();
-  }
-
-  public function fieldExists($table, $column) {
-    $schema = $this->introspectSchema($table);
-    return !empty($schema['fields'][$column]);
-  }
-
-  /**
-   * Generate SQL to create a new table from a Drupal schema definition.
-   *
-   * @param $name
-   *   The name of the table to create.
-   * @param $table
-   *   A Schema API table definition array.
-   * @return
-   *   An array of SQL statements to create the table.
-   */
-  public function createTableSql($name, $table) {
-    $sql = array();
-    $sql[] = "CREATE TABLE {" . $name . "} (\n" . $this->createColumnsSql($name, $table) . "\n);\n";
-    return array_merge($sql, $this->createIndexSql($name, $table));
-  }
-
-  /**
-   * Build the SQL expression for indexes.
-   */
-  protected function createIndexSql($tablename, $schema) {
-    $sql = array();
-    $info = $this->getPrefixInfo($tablename);
-    if (!empty($schema['unique keys'])) {
-      foreach ($schema['unique keys'] as $key => $fields) {
-        $sql[] = 'CREATE UNIQUE INDEX ' . $info['schema'] . '.' . $info['table'] . '_' . $key . ' ON ' . $info['table'] . ' (' . $this->createKeySql($fields) . "); \n";
-      }
-    }
-    if (!empty($schema['indexes'])) {
-      foreach ($schema['indexes'] as $key => $fields) {
-        $sql[] = 'CREATE INDEX ' . $info['schema'] . '.' . $info['table'] . '_' . $key . ' ON ' . $info['table'] . ' (' . $this->createKeySql($fields) . "); \n";
-      }
-    }
-    return $sql;
-  }
-
-  /**
-   * Build the SQL expression for creating columns.
-   */
-  protected function createColumnsSql($tablename, $schema) {
-    $sql_array = array();
-
-    // Add the SQL statement for each field.
-    foreach ($schema['fields'] as $name => $field) {
-      if (isset($field['type']) && $field['type'] == 'serial') {
-        if (isset($schema['primary key']) && ($key = array_search($name, $schema['primary key'])) !== FALSE) {
-          unset($schema['primary key'][$key]);
-        }
-      }
-      $sql_array[] = $this->createFieldSql($name, $this->processField($field));
-    }
-
-    // Process keys.
-    if (!empty($schema['primary key'])) {
-      $sql_array[] = " PRIMARY KEY (" . $this->createKeySql($schema['primary key']) . ")";
-    }
-
-    return implode(", \n", $sql_array);
-  }
-
-  /**
-   * Build the SQL expression for keys.
-   */
-  protected function createKeySql($fields) {
-    $return = array();
-    foreach ($fields as $field) {
-      if (is_array($field)) {
-        $return[] = $field[0];
-      }
-      else {
-        $return[] = $field;
-      }
-    }
-    return implode(', ', $return);
-  }
-
-  /**
-   * Set database-engine specific properties for a field.
-   *
-   * @param $field
-   *   A field description array, as specified in the schema documentation.
-   */
-  protected function processField($field) {
-    if (!isset($field['size'])) {
-      $field['size'] = 'normal';
-    }
-
-    // Set the correct database-engine specific datatype.
-    // In case one is already provided, force it to uppercase.
-    if (isset($field['sqlite_type'])) {
-      $field['sqlite_type'] = Unicode::strtoupper($field['sqlite_type']);
-    }
-    else {
-      $map = $this->getFieldTypeMap();
-      $field['sqlite_type'] = $map[$field['type'] . ':' . $field['size']];
-
-      // Numeric fields with a specified scale have to be stored as floats.
-      if ($field['sqlite_type'] === 'NUMERIC' && isset($field['scale'])) {
-        $field['sqlite_type'] = 'FLOAT';
-      }
-    }
-
-    if (isset($field['type']) && $field['type'] == 'serial') {
-      $field['auto_increment'] = TRUE;
-    }
-
-    return $field;
-  }
-
-  /**
-   * Create an SQL string for a field to be used in table creation or alteration.
-   *
-   * Before passing a field out of a schema definition into this function it has
-   * to be processed by db_processField().
-   *
-   * @param $name
-   *    Name of the field.
-   * @param $spec
-   *    The field specification, as per the schema data structure format.
-   */
-  protected function createFieldSql($name, $spec) {
-    if (!empty($spec['auto_increment'])) {
-      $sql = $name . " INTEGER PRIMARY KEY AUTOINCREMENT";
-      if (!empty($spec['unsigned'])) {
-        $sql .= ' CHECK (' . $name . '>= 0)';
-      }
-    }
-    else {
-      $sql = $name . ' ' . $spec['sqlite_type'];
-
-      if (in_array($spec['sqlite_type'], array('VARCHAR', 'TEXT'))) {
-        if (isset($spec['length'])) {
-          $sql .= '(' . $spec['length'] . ')';
-        }
-
-        if (isset($spec['binary']) && $spec['binary'] === FALSE) {
-          $sql .= ' COLLATE NOCASE_UTF8';
-        }
-      }
-
-      if (isset($spec['not null'])) {
-        if ($spec['not null']) {
-          $sql .= ' NOT NULL';
-        }
-        else {
-          $sql .= ' NULL';
-        }
-      }
-
-      if (!empty($spec['unsigned'])) {
-        $sql .= ' CHECK (' . $name . '>= 0)';
-      }
-
-      if (isset($spec['default'])) {
-        if (is_string($spec['default'])) {
-          $spec['default'] = $this->connection->quote($spec['default']);
-        }
-        $sql .= ' DEFAULT ' . $spec['default'];
-      }
-
-      if (empty($spec['not null']) && !isset($spec['default'])) {
-        $sql .= ' DEFAULT NULL';
-      }
-    }
-    return $sql;
-  }
-
-  /**
-   * This maps a generic data type in combination with its data size
-   * to the engine-specific data type.
-   */
-  public function getFieldTypeMap() {
-    // Put :normal last so it gets preserved by array_flip. This makes
-    // it much easier for modules (such as schema.module) to map
-    // database types back into schema types.
-    // $map does not use drupal_static as its value never changes.
-    static $map = array(
-      'varchar_ascii:normal' => 'VARCHAR',
-
-      'varchar:normal'  => 'VARCHAR',
-      'char:normal'     => 'CHAR',
-
-      'text:tiny'       => 'TEXT',
-      'text:small'      => 'TEXT',
-      'text:medium'     => 'TEXT',
-      'text:big'        => 'TEXT',
-      'text:normal'     => 'TEXT',
-
-      'serial:tiny'     => 'INTEGER',
-      'serial:small'    => 'INTEGER',
-      'serial:medium'   => 'INTEGER',
-      'serial:big'      => 'INTEGER',
-      'serial:normal'   => 'INTEGER',
-
-      'int:tiny'        => 'INTEGER',
-      'int:small'       => 'INTEGER',
-      'int:medium'      => 'INTEGER',
-      'int:big'         => 'INTEGER',
-      'int:normal'      => 'INTEGER',
-
-      'float:tiny'      => 'FLOAT',
-      'float:small'     => 'FLOAT',
-      'float:medium'    => 'FLOAT',
-      'float:big'       => 'FLOAT',
-      'float:normal'    => 'FLOAT',
-
-      'numeric:normal'  => 'NUMERIC',
-
-      'blob:big'        => 'BLOB',
-      'blob:normal'     => 'BLOB',
-    );
-    return $map;
-  }
-
-  public function renameTable($table, $new_name) {
-    if (!$this->tableExists($table)) {
-      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 SchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
-    }
-
-    $schema = $this->introspectSchema($table);
-
-    // SQLite doesn't allow you to rename tables outside of the current
-    // database. So the syntax '... RENAME TO database.table' would fail.
-    // So we must determine the full table name here rather than surrounding
-    // the table with curly braces in case the db_prefix contains a reference
-    // to a database outside of our existing database.
-    $info = $this->getPrefixInfo($new_name);
-    $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO ' . $info['table']);
-
-    // Drop the indexes, there is no RENAME INDEX command in SQLite.
-    if (!empty($schema['unique keys'])) {
-      foreach ($schema['unique keys'] as $key => $fields) {
-        $this->dropIndex($table, $key);
-      }
-    }
-    if (!empty($schema['indexes'])) {
-      foreach ($schema['indexes'] as $index => $fields) {
-        $this->dropIndex($table, $index);
-      }
-    }
-
-    // Recreate the indexes.
-    $statements = $this->createIndexSql($new_name, $schema);
-    foreach ($statements as $statement) {
-      $this->connection->query($statement);
-    }
-  }
-
-  public function dropTable($table) {
-    if (!$this->tableExists($table)) {
-      return FALSE;
-    }
-    $this->connection->tableDropped = TRUE;
-    $this->connection->query('DROP TABLE {' . $table . '}');
-    return TRUE;
-  }
-
-  public function addField($table, $field, $specification, $keys_new = array()) {
-    if (!$this->tableExists($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 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
-    // supports adding new fields to a table, in some simple cases. In most
-    // cases, we have to create a new table and copy the data over.
-    if (empty($keys_new) && (empty($specification['not null']) || isset($specification['default']))) {
-      // When we don't have to create new keys and we are not creating a
-      // NOT NULL column without a default value, we can use the quicker version.
-      $query = 'ALTER TABLE {' . $table . '} ADD ' . $this->createFieldSql($field, $this->processField($specification));
-      $this->connection->query($query);
-
-      // Apply the initial value if set.
-      if (isset($specification['initial'])) {
-        $this->connection->update($table)
-          ->fields(array($field => $specification['initial']))
-          ->execute();
-      }
-    }
-    else {
-      // We cannot add the field directly. Use the slower table alteration
-      // method, starting from the old schema.
-      $old_schema = $this->introspectSchema($table);
-      $new_schema = $old_schema;
-
-      // Add the new field.
-      $new_schema['fields'][$field] = $specification;
-
-      // Build the mapping between the old fields and the new fields.
-      $mapping = array();
-      if (isset($specification['initial'])) {
-        // If we have a initial value, copy it over.
-        $mapping[$field] = array(
-          'expression' => ':newfieldinitial',
-          'arguments' => array(':newfieldinitial' => $specification['initial']),
-        );
-      }
-      else {
-        // Else use the default of the field.
-        $mapping[$field] = NULL;
-      }
-
-      // Add the new indexes.
-      $new_schema += $keys_new;
-
-      $this->alterTable($table, $old_schema, $new_schema, $mapping);
-    }
-  }
-
-  /**
-   * Create a table with a new schema containing the old content.
-   *
-   * As SQLite does not support ALTER TABLE (with a few exceptions) it is
-   * necessary to create a new table and copy over the old content.
-   *
-   * @param $table
-   *   Name of the table to be altered.
-   * @param $old_schema
-   *   The old schema array for the table.
-   * @param $new_schema
-   *   The new schema array for the table.
-   * @param $mapping
-   *   An optional mapping between the fields of the old specification and the
-   *   fields of the new specification. An associative array, whose keys are
-   *   the fields of the new table, and values can take two possible forms:
-   *     - a simple string, which is interpreted as the name of a field of the
-   *       old table,
-   *     - an associative array with two keys 'expression' and 'arguments',
-   *       that will be used as an expression field.
-   */
-  protected function alterTable($table, $old_schema, $new_schema, array $mapping = array()) {
-    $i = 0;
-    do {
-      $new_table = $table . '_' . $i++;
-    } while ($this->tableExists($new_table));
-
-    $this->createTable($new_table, $new_schema);
-
-    // Build a SQL query to migrate the data from the old table to the new.
-    $select = $this->connection->select($table);
-
-    // Complete the mapping.
-    $possible_keys = array_keys($new_schema['fields']);
-    $mapping += array_combine($possible_keys, $possible_keys);
-
-    // Now add the fields.
-    foreach ($mapping as $field_alias => $field_source) {
-      // Just ignore this field (ie. use it's default value).
-      if (!isset($field_source)) {
-        continue;
-      }
-
-      if (is_array($field_source)) {
-        $select->addExpression($field_source['expression'], $field_alias, $field_source['arguments']);
-      }
-      else {
-        $select->addField($table, $field_source, $field_alias);
-      }
-    }
-
-    // Execute the data migration query.
-    $this->connection->insert($new_table)
-      ->from($select)
-      ->execute();
-
-    $old_count = $this->connection->query('SELECT COUNT(*) FROM {' . $table . '}')->fetchField();
-    $new_count = $this->connection->query('SELECT COUNT(*) FROM {' . $new_table . '}')->fetchField();
-    if ($old_count == $new_count) {
-      $this->dropTable($table);
-      $this->renameTable($new_table, $table);
-    }
-  }
-
-  /**
-   * Find out the schema of a table.
-   *
-   * This function uses introspection methods provided by the database to
-   * create a schema array. This is useful, for example, during update when
-   * the old schema is not available.
-   *
-   * @param $table
-   *   Name of the table.
-   * @return
-   *   An array representing the schema, from drupal_get_schema().
-   */
-  protected function introspectSchema($table) {
-    $mapped_fields = array_flip($this->getFieldTypeMap());
-    $schema = array(
-      'fields' => array(),
-      'primary key' => array(),
-      'unique keys' => array(),
-      'indexes' => array(),
-    );
-
-    $info = $this->getPrefixInfo($table);
-    $result = $this->connection->query('PRAGMA ' . $info['schema'] . '.table_info(' . $info['table'] . ')');
-    foreach ($result as $row) {
-      if (preg_match('/^([^(]+)\((.*)\)$/', $row->type, $matches)) {
-        $type = $matches[1];
-        $length = $matches[2];
-      }
-      else {
-        $type = $row->type;
-        $length = NULL;
-      }
-      if (isset($mapped_fields[$type])) {
-        list($type, $size) = explode(':', $mapped_fields[$type]);
-        $schema['fields'][$row->name] = array(
-          'type' => $type,
-          'size' => $size,
-          'not null' => !empty($row->notnull),
-          'default' => trim($row->dflt_value, "'"),
-        );
-        if ($length) {
-          $schema['fields'][$row->name]['length'] = $length;
-        }
-        if ($row->pk) {
-          $schema['primary key'][] = $row->name;
-        }
-      }
-      else {
-        new \Exception("Unable to parse the column type " . $row->type);
-      }
-    }
-    $indexes = array();
-    $result = $this->connection->query('PRAGMA ' . $info['schema'] . '.index_list(' . $info['table'] . ')');
-    foreach ($result as $row) {
-      if (strpos($row->name, 'sqlite_autoindex_') !== 0) {
-        $indexes[] = array(
-          'schema_key' => $row->unique ? 'unique keys' : 'indexes',
-          'name' => $row->name,
-        );
-      }
-    }
-    foreach ($indexes as $index) {
-      $name = $index['name'];
-      // Get index name without prefix.
-      $index_name = substr($name, strlen($info['table']) + 1);
-      $result = $this->connection->query('PRAGMA ' . $info['schema'] . '.index_info(' . $name . ')');
-      foreach ($result as $row) {
-        $schema[$index['schema_key']][$index_name][] = $row->name;
-      }
-    }
-    return $schema;
-  }
-
-  public function dropField($table, $field) {
-    if (!$this->fieldExists($table, $field)) {
-      return FALSE;
-    }
-
-    $old_schema = $this->introspectSchema($table);
-    $new_schema = $old_schema;
-
-    unset($new_schema['fields'][$field]);
-
-    // Handle possible primary key changes.
-    if (isset($new_schema['primary key']) && ($key = array_search($field, $new_schema['primary key'])) !== FALSE) {
-      unset($new_schema['primary key'][$key]);
-    }
-
-    // Handle possible index changes.
-    foreach ($new_schema['indexes'] as $index => $fields) {
-      foreach ($fields as $key => $field_name) {
-        if ($field_name == $field) {
-          unset($new_schema['indexes'][$index][$key]);
-        }
-      }
-      // If this index has no more fields then remove it.
-      if (empty($new_schema['indexes'][$index])) {
-        unset($new_schema['indexes'][$index]);
-      }
-    }
-    $this->alterTable($table, $old_schema, $new_schema);
-    return TRUE;
-  }
-
-  public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
-    if (!$this->fieldExists($table, $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 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);
-    $new_schema = $old_schema;
-
-    // Map the old field to the new field.
-    if ($field != $field_new) {
-      $mapping[$field_new] = $field;
-    }
-    else {
-      $mapping = array();
-    }
-
-    // Remove the previous definition and swap in the new one.
-    unset($new_schema['fields'][$field]);
-    $new_schema['fields'][$field_new] = $spec;
-
-    // Map the former indexes to the new column name.
-    $new_schema['primary key'] = $this->mapKeyDefinition($new_schema['primary key'], $mapping);
-    foreach (array('unique keys', 'indexes') as $k) {
-      foreach ($new_schema[$k] as &$key_definition) {
-        $key_definition = $this->mapKeyDefinition($key_definition, $mapping);
-      }
-    }
-
-    // Add in the keys from $keys_new.
-    if (isset($keys_new['primary key'])) {
-      $new_schema['primary key'] = $keys_new['primary key'];
-    }
-    foreach (array('unique keys', 'indexes') as $k) {
-      if (!empty($keys_new[$k])) {
-        $new_schema[$k] = $keys_new[$k] + $new_schema[$k];
-      }
-    }
-
-    $this->alterTable($table, $old_schema, $new_schema, $mapping);
-  }
-
-  /**
-   * Utility method: rename columns in an index definition according to a new mapping.
-   *
-   * @param $key_definition
-   *   The key definition.
-   * @param $mapping
-   *   The new mapping.
-   */
-  protected function mapKeyDefinition(array $key_definition, array $mapping) {
-    foreach ($key_definition as &$field) {
-      // The key definition can be an array($field, $length).
-      if (is_array($field)) {
-        $field = &$field[0];
-      }
-      if (isset($mapping[$field])) {
-        $field = $mapping[$field];
-      }
-    }
-    return $key_definition;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function addIndex($table, $name, $fields, array $spec) {
-    if (!$this->tableExists($table)) {
-      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 SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
-    }
-
-    $schema['indexes'][$name] = $fields;
-    $statements = $this->createIndexSql($table, $schema);
-    foreach ($statements as $statement) {
-      $this->connection->query($statement);
-    }
-  }
-
-  public function indexExists($table, $name) {
-    $info = $this->getPrefixInfo($table);
-
-    return $this->connection->query('PRAGMA ' . $info['schema'] . '.index_info(' . $info['table'] . '_' . $name . ')')->fetchField() != '';
-  }
-
-  public function dropIndex($table, $name) {
-    if (!$this->indexExists($table, $name)) {
-      return FALSE;
-    }
-
-    $info = $this->getPrefixInfo($table);
-
-    $this->connection->query('DROP INDEX ' . $info['schema'] . '.' . $info['table'] . '_' . $name);
-    return TRUE;
-  }
-
-  public function addUniqueKey($table, $name, $fields) {
-    if (!$this->tableExists($table)) {
-      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 SchemaObjectExistsException(t("Cannot add unique key @name to table @table: unique key already exists.", array('@table' => $table, '@name' => $name)));
-    }
-
-    $schema['unique keys'][$name] = $fields;
-    $statements = $this->createIndexSql($table, $schema);
-    foreach ($statements as $statement) {
-      $this->connection->query($statement);
-    }
-  }
-
-  public function dropUniqueKey($table, $name) {
-    if (!$this->indexExists($table, $name)) {
-      return FALSE;
-    }
-
-    $info = $this->getPrefixInfo($table);
-
-    $this->connection->query('DROP INDEX ' . $info['schema'] . '.' . $info['table'] . '_' . $name);
-    return TRUE;
-  }
-
-  public function addPrimaryKey($table, $fields) {
-    if (!$this->tableExists($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 SchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
-    }
-
-    $new_schema['primary key'] = $fields;
-    $this->alterTable($table, $old_schema, $new_schema);
-  }
-
-  public function dropPrimaryKey($table) {
-    $old_schema = $this->introspectSchema($table);
-    $new_schema = $old_schema;
-
-    if (empty($new_schema['primary key'])) {
-      return FALSE;
-    }
-
-    unset($new_schema['primary key']);
-    $this->alterTable($table, $old_schema, $new_schema);
-    return TRUE;
-  }
-
-  public function fieldSetDefault($table, $field, $default) {
-    if (!$this->fieldExists($table, $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);
-    $new_schema = $old_schema;
-
-    $new_schema['fields'][$field]['default'] = $default;
-    $this->alterTable($table, $old_schema, $new_schema);
-  }
-
-  public function fieldSetNoDefault($table, $field) {
-    if (!$this->fieldExists($table, $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);
-    $new_schema = $old_schema;
-
-    unset($new_schema['fields'][$field]['default']);
-    $this->alterTable($table, $old_schema, $new_schema);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function findTables($table_expression) {
-    $tables = [];
-
-    // The SQLite implementation doesn't need to use the same filtering strategy
-    // as the parent one because individually prefixed tables live in their own
-    // schema (database), which means that neither the main database nor any
-    // attached one will contain a prefixed table name, so we just need to loop
-    // over all known schemas and filter by the user-supplied table expression.
-    $attached_dbs = $this->connection->getAttachedDatabases();
-    foreach ($attached_dbs as $schema) {
-      // Can't use query placeholders for the schema because the query would
-      // have to be :prefixsqlite_master, which does not work. We also need to
-      // ignore the internal SQLite tables.
-      $result = db_query("SELECT name FROM " . $schema . ".sqlite_master WHERE type = :type AND name LIKE :table_name AND name NOT LIKE :pattern", array(
-        ':type' => 'table',
-        ':table_name' => $table_expression,
-        ':pattern' => 'sqlite_%',
-      ));
-      $tables += $result->fetchAllKeyed(0, 0);
-    }
-
-    return $tables;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Select.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Select.php
deleted file mode 100644
index 8f2fdb7..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Select.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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
deleted file mode 100644
index bfa494f..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php
+++ /dev/null
@@ -1,149 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\sqlite\Statement.
- */
-
-namespace Drupal\Core\Database\Driver\sqlite;
-
-use Drupal\Core\Database\StatementPrefetch;
-use Drupal\Core\Database\StatementInterface;
-
-/**
- * Specific SQLite implementation of DatabaseConnection.
- *
- * The PDO SQLite driver only closes SELECT statements when the PDOStatement
- * destructor is called and SQLite does not allow data change (INSERT,
- * UPDATE etc) on a table which has open SELECT statements. This is a
- * user-space mock of PDOStatement that buffers all the data and doesn't
- * have those limitations.
- */
-class Statement extends StatementPrefetch implements StatementInterface {
-
-  /**
-   * {@inheritdoc}
-   *
-   * 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->pdoConnection->prepare($query);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  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
deleted file mode 100644
index 736dbcc..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Transaction.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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
deleted file mode 100644
index a0171c4..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Truncate.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \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) . '} ';
-  }
-}
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Update.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Update.php
deleted file mode 100644
index aca3c95..0000000
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Update.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Driver\sqlite\Update.
- */
-
-namespace Drupal\Core\Database\Driver\sqlite;
-
-use Drupal\Core\Database\Query\Update as QueryUpdate;
-
-class Update extends QueryUpdate { }
diff --git a/core/lib/Drupal/Core/Extension/Discovery/RecursiveExtensionFilterIterator.php b/core/lib/Drupal/Core/Extension/Discovery/RecursiveExtensionFilterIterator.php
index d5da27c..ffe041d 100644
--- a/core/lib/Drupal/Core/Extension/Discovery/RecursiveExtensionFilterIterator.php
+++ b/core/lib/Drupal/Core/Extension/Discovery/RecursiveExtensionFilterIterator.php
@@ -44,6 +44,7 @@ class RecursiveExtensionFilterIterator extends \RecursiveFilterIterator {
    * @var array
    */
   protected $whitelist = array(
+    'drivers',
     'profiles',
     'modules',
     'themes',
diff --git a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
index c088eed..653c435 100644
--- a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
+++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php
@@ -140,8 +140,8 @@ public function __construct($root, $use_file_cache = TRUE, $profile_directories
    * compatible with the current version of Drupal core.
    *
    * @param string $type
-   *   The extension type to search for. One of 'profile', 'module', 'theme', or
-   *   'theme_engine'.
+   *   The extension type to search for. One of 'profile', 'module', 'theme',
+   *   'theme_engine', or 'driver'.
    * @param bool $include_tests
    *   (optional) Whether to explicitly include or exclude test extensions. By
    *   default, test extensions are only discovered when in a test environment.
diff --git a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
index 4d0f9fe..b442506 100644
--- a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
+++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
@@ -146,11 +146,17 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
     $driver = $form_state->getValue('driver');
     $database = $form_state->getValue($driver);
     $drivers = drupal_get_database_types();
+
     $reflection = new \ReflectionClass($drivers[$driver]);
-    $install_namespace = $reflection->getNamespaceName();
+
+    $database['driver'] = $driver;
+    // Record the effective filesystem path of this driver (without /Install).
+    $database['path'] = dirname(dirname($reflection->getFileName()));
+
     // Cut the trailing \Install from namespace.
+    // @todo 'namespace' is theoretically obsolete now?
+    $install_namespace = $reflection->getNamespaceName();
     $database['namespace'] = substr($install_namespace, 0, strrpos($install_namespace, '\\'));
-    $database['driver'] = $driver;
 
     $form_state->set('database', $database);
     $errors = install_database_errors($database, $form_state->getValue('settings_file'));
diff --git a/core/modules/comment/tests/src/Unit/CommentStatisticsUnitTest.php b/core/modules/comment/tests/src/Unit/CommentStatisticsUnitTest.php
index c6f897a..ac918f6 100644
--- a/core/modules/comment/tests/src/Unit/CommentStatisticsUnitTest.php
+++ b/core/modules/comment/tests/src/Unit/CommentStatisticsUnitTest.php
@@ -55,7 +55,11 @@ class CommentStatisticsUnitTest extends UnitTestCase {
    * Sets up required mocks and the CommentStatistics service under test.
    */
   protected function setUp() {
+<<<<<<< HEAD
     $this->statement = $this->getMockBuilder('Drupal\Core\Database\Driver\sqlite\Statement')
+=======
+    $this->statement = $this->getMockBuilder('Drupal\fake\FakeStatement')
+>>>>>>> Applying patch from issue 2209307 comment 34
       ->disableOriginalConstructor()
       ->getMock();
 
diff --git a/core/modules/migrate/tests/src/Unit/MigrateTestCase.php b/core/modules/migrate/tests/src/Unit/MigrateTestCase.php
index 768e0fc..f2ca576 100644
--- a/core/modules/migrate/tests/src/Unit/MigrateTestCase.php
+++ b/core/modules/migrate/tests/src/Unit/MigrateTestCase.php
@@ -11,6 +11,10 @@
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\migrate\Entity\MigrationInterface;
 use Drupal\Tests\UnitTestCase;
+<<<<<<< HEAD
+=======
+use Drupal\fake\FakeConnection;
+>>>>>>> Applying patch from issue 2209307 comment 34
 
 /**
  * Provides setup and helper methods for Migrate module tests.
@@ -96,7 +100,11 @@ protected function getMigration() {
    * @param array $connection_options
    *  (optional) Options for the database connection.
    *
+<<<<<<< HEAD
    * @return \Drupal\Core\Database\Driver\sqlite\Connection
+=======
+   * @return \Drupal\fake\FakeConnection
+>>>>>>> Applying patch from issue 2209307 comment 34
    *   The database connection.
    */
   protected function getDatabase(array $database_contents, $connection_options = []) {
diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php
index 62e4c9f..cdaad14 100644
--- a/core/modules/simpletest/src/TestBase.php
+++ b/core/modules/simpletest/src/TestBase.php
@@ -1239,9 +1239,18 @@ private function prepareEnvironment() {
     // Reset statics.
     drupal_static_reset();
 
+<<<<<<< HEAD
     // Ensure there is no service container.
     $this->container = NULL;
     \Drupal::unsetContainer();
+=======
+    // Ensure there is a minimal service container.
+    // @todo Restore the ability to completely remove the container.
+    $container = new ContainerBuilder();
+    $container->set('class_loader', $this->originalContainer->get('class_loader'));;
+    $this->container = $container;
+    \Drupal::setContainer($container);
+>>>>>>> Applying patch from issue 2209307 comment 34
 
     // Unset globals.
     unset($GLOBALS['config_directories']);
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index fcdb00a..9dcf65d 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -904,6 +904,7 @@ protected function installParameters() {
     unset($connection_info['default']['namespace']);
     unset($connection_info['default']['pdo']);
     unset($connection_info['default']['init_commands']);
+<<<<<<< HEAD
     // Remove database connection info that is not used by SQLite.
     if ($driver == 'sqlite') {
       unset($connection_info['default']['username']);
@@ -911,6 +912,9 @@ protected function installParameters() {
       unset($connection_info['default']['host']);
       unset($connection_info['default']['port']);
     }
+=======
+    unset($connection_info['default']['path']);
+>>>>>>> Applying patch from issue 2209307 comment 34
     $parameters = array(
       'interactive' => FALSE,
       'parameters' => array(
diff --git a/core/modules/system/src/Tests/Installer/InstallerTest.php b/core/modules/system/src/Tests/Installer/InstallerTest.php
index b17e3e7..420fc82 100644
--- a/core/modules/system/src/Tests/Installer/InstallerTest.php
+++ b/core/modules/system/src/Tests/Installer/InstallerTest.php
@@ -28,7 +28,7 @@ public function testInstaller() {
     // Verify that the confirmation message appears.
     require_once \Drupal::root() . '/core/includes/install.inc';
     $this->assertRaw(t('Congratulations, you installed @drupal!', array(
-      '@drupal' => drupal_install_profile_distribution_name(),
+      '@drupal' => 'Drupal',
     )));
   }
 
diff --git a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
index 6009e65..b53a3e4 100644
--- a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
+++ b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
@@ -8,8 +8,12 @@
 namespace Drupal\Tests\Component\EventDispatcher;
 
 use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
+<<<<<<< HEAD
 use Symfony\Component\DependencyInjection\Container;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+=======
+use Drupal\Tests\UnitTestCase;
+>>>>>>> Applying patch from issue 2209307 comment 34
 use Symfony\Component\EventDispatcher\Event;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\EventDispatcher\Tests\AbstractEventDispatcherTest;
@@ -29,7 +33,11 @@
  *
  * @group Symfony
  */
+<<<<<<< HEAD
 class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest
+=======
+class ContainerAwareEventDispatcherTest extends UnitTestCase
+>>>>>>> Applying patch from issue 2209307 comment 34
 {
     protected function createEventDispatcher()
     {
diff --git a/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php b/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php
index 4f4c803..35ba34f 100644
--- a/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php
+++ b/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Database;
 
+use Drupal\fake\FakeConnection;
 use Drupal\Tests\Core\Database\Stub\StubConnection;
 use Drupal\Tests\Core\Database\Stub\StubPDO;
 use Drupal\Tests\UnitTestCase;
@@ -157,19 +158,16 @@ public function providerGetDriverClass() {
       array(
         'nonexistent_class',
         'stub',
-        '\\',
         'nonexistent_class',
       ),
       array(
-        'Drupal\\Core\\Database\\Driver\\mysql\\Select',
+        'Drupal\\mysql\\Select',
         'mysql',
-        NULL,
         'Select',
       ),
       array(
-        'Drupal\\Tests\\Core\\Database\\Stub\\Driver\\Schema',
-        'stub',
-        'Drupal\\Tests\\Core\\Database\\Stub\\Driver',
+        'Drupal\\fake\\Schema',
+        'fake',
         'Schema',
       ),
     );
@@ -180,9 +178,9 @@ public function providerGetDriverClass() {
    *
    * @dataProvider providerGetDriverClass
    */
-  public function testGetDriverClass($expected, $driver, $namespace, $class) {
+  public function testGetDriverClass($expected, $driver, $class) {
     $mock_pdo = $this->getMock('Drupal\Tests\Core\Database\Stub\StubPDO');
-    $connection = new StubConnection($mock_pdo, array('namespace' => $namespace));
+    $connection = new StubConnection($mock_pdo, array());
     // Set the driver using our stub class' public property.
     $connection->driver = $driver;
     $this->assertEquals($expected, $connection->getDriverClass($class));
@@ -200,9 +198,8 @@ public function testGetDriverClass($expected, $driver, $namespace, $class) {
   public function providerSchema() {
     return array(
       array(
-        'Drupal\\Tests\\Core\\Database\\Stub\\Driver\\Schema',
-        'stub',
-        'Drupal\\Tests\\Core\\Database\\Stub\\Driver',
+        'Drupal\\fake\\Schema',
+        'fake',
       ),
     );
   }
@@ -212,9 +209,8 @@ public function providerSchema() {
    *
    * @dataProvider providerSchema
    */
-  public function testSchema($expected, $driver, $namespace) {
-    $mock_pdo = $this->getMock('Drupal\Tests\Core\Database\Stub\StubPDO');
-    $connection = new StubConnection($mock_pdo, array('namespace' => $namespace));
+  public function testSchema($expected, $driver) {
+    $connection = new FakeConnection(array());
     $connection->driver = $driver;
     $this->assertInstanceOf($expected, $connection->schema());
   }
@@ -223,16 +219,10 @@ public function testSchema($expected, $driver, $namespace) {
    * Test Connection::destroy().
    */
   public function testDestroy() {
-    $mock_pdo = $this->getMock('Drupal\Tests\Core\Database\Stub\StubPDO');
-    // Mocking StubConnection gives us access to the $schema attribute.
-    $connection = $this->getMock(
-      'Drupal\Tests\Core\Database\Stub\StubConnection',
-      NULL,
-      array($mock_pdo, array('namespace' => 'Drupal\\Tests\\Core\\Database\\Stub\\Driver'))
-    );
+    $connection = new FakeConnection(array());
     // Generate a schema object in order to verify that we've NULLed it later.
     $this->assertInstanceOf(
-      'Drupal\\Tests\\Core\\Database\\Stub\\Driver\\Schema',
+      'Drupal\\fake\\Schema',
       $connection->schema()
     );
     $connection->destroy();
diff --git a/core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php b/core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php
deleted file mode 100644
index 2d855b7..0000000
--- a/core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\Core\Database\Stub\Driver\Schema.
- */
-
-namespace Drupal\Tests\Core\Database\Stub\Driver;
-
-/**
- * A very minimal class for testing purposes.
- *
- * @see ConnectionTest::testGetDriverClass()
- * @see ConnectionTest::testSchema()
- */
-class Schema {
-  // No-op.
-}
diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php
index 31ac4cd..63e8f45 100644
--- a/core/tests/bootstrap.php
+++ b/core/tests/bootstrap.php
@@ -52,6 +52,7 @@ function drupal_phpunit_contrib_extension_directory_roots() {
     $path = "$sites_path/$site";
     $paths[] = is_dir("$path/modules") ? realpath("$path/modules") : NULL;
     $paths[] = is_dir("$path/profiles") ? realpath("$path/profiles") : NULL;
+    $paths[] = is_dir("$path/drivers") ? realpath("$path/drivers") : NULL;
   }
   return array_filter($paths);
 }
@@ -85,9 +86,22 @@ function drupal_phpunit_get_extension_namespaces($dirs) {
 $loader->add('Drupal\\Tests', __DIR__);
 $loader->add('Drupal\\KernelTests', __DIR__);
 
+<<<<<<< HEAD
 if (!isset($GLOBALS['namespaces'])) {
   // Scan for arbitrary extension namespaces from core and contrib.
   $extension_roots = drupal_phpunit_contrib_extension_directory_roots();
+=======
+// Scan for arbitrary extension namespaces from core and contrib.
+$extension_roots = array_merge(array(
+  __DIR__ . '/../modules',
+  __DIR__ . '/../profiles',
+  __DIR__ . '/../drivers',
+), drupal_phpunit_contrib_extension_directory_roots());
+
+$dirs = array_map('drupal_phpunit_find_extension_directories', $extension_roots);
+$dirs = array_reduce($dirs, 'array_merge', array());
+drupal_phpunit_register_extension_dirs($loader, $dirs);
+>>>>>>> Applying patch from issue 2209307 comment 34
 
   $dirs = array_map('drupal_phpunit_find_extension_directories', $extension_roots);
   $dirs = array_reduce($dirs, 'array_merge', array());
