Commit d79e4a65 authored by catch's avatar catch
Browse files

Issue #3106531 by mondrake, daffie, Rithesh BK, catch, xjm: Notify in Status...

Issue #3106531 by mondrake, daffie, Rithesh BK, catch, xjm: Notify in Status Report that per-table database prefixes are no longer supported, and will throw errors in Drupal 10.0
parent e1ab1133
Loading
Loading
Loading
Loading
+6 −39
Original line number Diff line number Diff line
@@ -138,50 +138,17 @@
 * request as needed.  The fourth line creates a new database with a name of
 * "extra".
 *
 * You can optionally set prefixes for some or all database table names
 * by using the 'prefix' setting. If a prefix is specified, the table
 * name will be prepended with its value. Be sure to use valid database
 * characters only, usually alphanumeric and underscore. If no prefixes
 * are desired, leave it as an empty string ''.
 * You can optionally set a prefix for all database table names by using the
 * 'prefix' setting. If a prefix is specified, the table name will be prepended
 * with its value. Be sure to use valid database characters only, usually
 * alphanumeric and underscore. If no prefix is desired, do not set the 'prefix'
 * key or set its value to an empty string ''.
 *
 * To have all database names prefixed, set 'prefix' as a string:
 * For example, to have all database table prefixed with 'main_', set:
 * @code
 *   'prefix' => 'main_',
 * @endcode
 *
 * Per-table prefixes are deprecated as of Drupal 8.2, and will be removed in
 * Drupal 9.0. After that, only a single prefix for all tables will be
 * supported.
 *
 * To provide prefixes for specific tables, set 'prefix' as an array.
 * The array's keys are the table names and the values are the prefixes.
 * The 'default' element is mandatory and holds the prefix for any tables
 * not specified elsewhere in the array. Example:
 * @code
 *   'prefix' => [
 *     'default'   => 'main_',
 *     'users'     => 'shared_',
 *     'sessions'  => 'shared_',
 *     'role'      => 'shared_',
 *     'authmap'   => 'shared_',
 *   ],
 * @endcode
 * You can also use a reference to a schema/database as a prefix. This may be
 * useful if your Drupal installation exists in a schema that is not the default
 * or you want to access several databases from the same code base at the same
 * time.
 * Example:
 * @code
 *   'prefix' => [
 *     'default'   => 'main.',
 *     'users'     => 'shared.',
 *     'sessions'  => 'shared.',
 *     'role'      => 'shared.',
 *     'authmap'   => 'shared.',
 *   ];
 * @endcode
 * NOTE: MySQL and SQLite's definition of a schema is a database.
 *
 * Advanced users can add or override initial commands to execute when
 * connecting to the database server, as well as PDO connection settings. For
 * example, to enable MySQL SELECT queries to exceed the max_join_size system
+1 −1
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ protected function getDatabaseConnection(InputInterface $input) {
    $prefix = $input->getOption('prefix');
    if ($prefix) {
      $info = Database::getConnectionInfo($key)['default'];
      $info['prefix']['default'] = $prefix;
      $info['prefix'] = $prefix;

      Database::removeConnection($key);
      Database::addConnectionInfo($key, 'default', $info);
+41 −8
Original line number Diff line number Diff line
@@ -227,6 +227,8 @@ abstract class Connection {
   *   - prefix
   *   - namespace
   *   - Other driver-specific options.
   *   An 'extra_prefix' option may be present to allow BC for attaching
   *   per-table prefixes, but it is meant for internal use only.
   */
  public function __construct(\PDO $connection, array $connection_options) {
    if ($this->identifierQuotes === NULL) {
@@ -235,12 +237,47 @@ public function __construct(\PDO $connection, array $connection_options) {
    }

    assert(count($this->identifierQuotes) === 2 && Inspector::assertAllStrings($this->identifierQuotes), '\Drupal\Core\Database\Connection::$identifierQuotes must contain 2 string values');

    // The 'transactions' option is deprecated.
    if (isset($connection_options['transactions'])) {
      @trigger_error('Passing a \'transactions\' connection option to ' . __METHOD__ . ' is deprecated in drupal:9.1.0 and is removed in drupal:10.0.0. All database drivers must support transactions. See https://www.drupal.org/node/2278745', E_USER_DEPRECATED);
      unset($connection_options['transactions']);
    }

    // Manage the table prefix.
    if (isset($connection_options['prefix']) && is_array($connection_options['prefix'])) {
      if (count($connection_options['prefix']) > 1) {
        // If there are keys left besides the 'default' one, we are in a
        // multi-prefix scenario (for per-table prefixing, or migrations).
        // In that case, we put the non-default keys in a 'extra_prefix' key
        // to avoid mixing up with the normal 'prefix', which is a string since
        // Drupal 9.1.0.
        $prefix = $connection_options['prefix']['default'] ?? '';
        unset($connection_options['prefix']['default']);
        if (isset($connection_options['extra_prefix'])) {
          $connection_options['extra_prefix'] = array_merge($connection_options['extra_prefix'], $connection_options['prefix']);
        }
        else {
          $connection_options['extra_prefix'] = $connection_options['prefix'];
        }
      }
      else {
        $prefix = $connection_options['prefix']['default'] ?? '';
      }
      $connection_options['prefix'] = $prefix;
    }

    // Initialize and prepare the connection prefix.
    if (!isset($connection_options['extra_prefix'])) {
      $prefix = $connection_options['prefix'] ?? '';
    }
    else {
      $default_prefix = $connection_options['prefix'] ?? '';
      $prefix = $connection_options['extra_prefix'];
      $prefix['default'] = $default_prefix;
    }
    $this->setPrefix($prefix);

    // Work out the database driver namespace if none is provided. This normally
    // written to setting.php by installer or set by
    // \Drupal\Core\Database\Database::parseConnectionInfo().
@@ -254,9 +291,6 @@ public function __construct(\PDO $connection, array $connection_options) {
      @trigger_error('Support for database drivers located in the "drivers/lib/Drupal/Driver/Database" directory is deprecated in drupal:9.1.0 and is removed in drupal:10.0.0. Contributed and custom database drivers should be provided by modules and use the namespace "Drupal\MODULE_NAME\Driver\Database\DRIVER_NAME". See https://www.drupal.org/node/3123251', E_USER_DEPRECATED);
    }

    // Initialize and prepare the connection prefix.
    $this->setPrefix(isset($connection_options['prefix']) ? $connection_options['prefix'] : '');

    // Set a Statement class, unless the driver opted out.
    // @todo remove this in Drupal 10 https://www.drupal.org/node/3177490
    if (!empty($this->statementClass)) {
@@ -407,8 +441,7 @@ public function getConnectionOptions() {
   * Set the list of prefixes used by this database connection.
   *
   * @param array|string $prefix
   *   Either a single prefix, or an array of prefixes, in any of the multiple
   *   forms documented in default.settings.php.
   *   Either a single prefix, or an array of prefixes.
   */
  protected function setPrefix($prefix) {
    if (is_array($prefix)) {
@@ -1994,7 +2027,7 @@ public static function createConnectionOptionsFromUrl($url, $root) {
    }

    if (!empty($url_components['fragment'])) {
      $database['prefix']['default'] = $url_components['fragment'];
      $database['prefix'] = $url_components['fragment'];
    }

    return $database;
@@ -2050,8 +2083,8 @@ public static function createUrlFromConnectionOptions(array $connection_options)
      $db_url .= '?module=' . $connection_options['module'];
    }

    if (isset($connection_options['prefix']['default']) && $connection_options['prefix']['default'] !== '') {
      $db_url .= '#' . $connection_options['prefix']['default'];
    if (isset($connection_options['prefix']) && $connection_options['prefix'] !== '') {
      $db_url .= '#' . $connection_options['prefix'];
    }

    return $db_url;
+16 −9
Original line number Diff line number Diff line
@@ -216,17 +216,24 @@ final public static function parseConnectionInfo(array $info) {
    }

    // Parse the prefix information.
    // @todo in Drupal 10, fail hard if $info['prefix'] is an array.
    // @see https://www.drupal.org/project/drupal/issues/3124382
    if (!isset($info['prefix'])) {
      // Default to an empty prefix.
      $info['prefix'] = [
        'default' => '',
      ];
    }
    elseif (!is_array($info['prefix'])) {
      // Transform the flat form into an array form.
      $info['prefix'] = [
        'default' => $info['prefix'],
      ];
      $info['prefix'] = '';
    }
    elseif (is_array($info['prefix'])) {
      $prefix = $info['prefix']['default'] ?? '';
      unset($info['prefix']['default']);
      // If there are keys left besides the 'default' one, we are in a
      // multi-prefix scenario (for per-table prefixing, or migrations).
      // In that case, we put the non-default keys in a 'extra_prefix' key
      // to avoid mixing up with the normal 'prefix', which is a string since
      // Drupal 9.1.0.
      if (count($info['prefix'])) {
        $info['extra_prefix'] = $info['prefix'];
      }
      $info['prefix'] = $prefix;
    }

    // Fallback for Drupal 7 settings.php if namespace is not provided.
+2 −2
Original line number Diff line number Diff line
@@ -514,8 +514,8 @@ public static function createUrlFromConnectionOptions(array $connection_options)

    $db_url = 'sqlite://localhost/' . $connection_options['database'];

    if (isset($connection_options['prefix']['default']) && $connection_options['prefix']['default'] !== NULL && $connection_options['prefix']['default'] !== '') {
      $db_url .= '#' . $connection_options['prefix']['default'];
    if (isset($connection_options['prefix']) && $connection_options['prefix'] !== '') {
      $db_url .= '#' . $connection_options['prefix'];
    }

    return $db_url;
Loading