diff --git a/core/assets/scaffold/files/default.settings.php b/core/assets/scaffold/files/default.settings.php index 64c749d4d012bd76018457db99d0e32e6ea45789..718890224b488ef2ded4b4da4ba6fcc034daceab 100644 --- a/core/assets/scaffold/files/default.settings.php +++ b/core/assets/scaffold/files/default.settings.php @@ -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 diff --git a/core/lib/Drupal/Core/Command/DbCommandBase.php b/core/lib/Drupal/Core/Command/DbCommandBase.php index d5a80e08d21a7ff2a9dbf22e86bfb8a4325d5117..6845b96075562c822d26834852085b0819cf68ce 100644 --- a/core/lib/Drupal/Core/Command/DbCommandBase.php +++ b/core/lib/Drupal/Core/Command/DbCommandBase.php @@ -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); diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php index ee8e7640e3c10d2060db3cff98bd18a51ede37e1..f19f5c6b9662360953b9193287f01ee0c29f5058 100644 --- a/core/lib/Drupal/Core/Database/Connection.php +++ b/core/lib/Drupal/Core/Database/Connection.php @@ -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; diff --git a/core/lib/Drupal/Core/Database/Database.php b/core/lib/Drupal/Core/Database/Database.php index f2d5f9c2bdd4ac854e6f2ce7ce6b8a306b0ed467..2771166e48f9c415dd4955d5efeaa28f1ebcf143 100644 --- a/core/lib/Drupal/Core/Database/Database.php +++ b/core/lib/Drupal/Core/Database/Database.php @@ -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. diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php index 4a43d11aa5679fd632e846101eb2176a8006fff5..bb1c15def90a669892c0ff666f6f3672843a4363 100644 --- a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php +++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php @@ -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; diff --git a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php index 829c226950dbfe0e7a73937d37240d4a6b2a5ad1..03631793c29e77dd9ad4c78dbb09b3957eebecd5 100644 --- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php +++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php @@ -514,7 +514,6 @@ protected function rebuildAll() { protected function installParameters() { $connection_info = Database::getConnectionInfo(); $driver = $connection_info['default']['driver']; - $connection_info['default']['prefix'] = $connection_info['default']['prefix']['default']; unset($connection_info['default']['driver']); unset($connection_info['default']['namespace']); unset($connection_info['default']['pdo']); diff --git a/core/lib/Drupal/Core/Test/TestSetupTrait.php b/core/lib/Drupal/Core/Test/TestSetupTrait.php index f78455ca550d9762fd253eef84e1f4c554904383..de780437b88911504193aebec8f181c1c6425a08 100644 --- a/core/lib/Drupal/Core/Test/TestSetupTrait.php +++ b/core/lib/Drupal/Core/Test/TestSetupTrait.php @@ -167,9 +167,7 @@ protected function changeDatabasePrefix() { foreach ($connection_info as $target => $value) { // Replace the full table prefix definition to ensure that no table // prefixes of the test runner leak into the test. - $connection_info[$target]['prefix'] = [ - 'default' => $value['prefix']['default'] . $this->databasePrefix, - ]; + $connection_info[$target]['prefix'] = $value['prefix'] . $this->databasePrefix; } Database::addConnectionInfo('default', 'default', $connection_info['default']); } diff --git a/core/modules/migrate/tests/src/Kernel/MigrateTestBase.php b/core/modules/migrate/tests/src/Kernel/MigrateTestBase.php index 38e290819cd9580b6f5dc2e1bf631f506b8e2269..25c1b4e7301ec2be519cb16c15be85acce2e0863 100644 --- a/core/modules/migrate/tests/src/Kernel/MigrateTestBase.php +++ b/core/modules/migrate/tests/src/Kernel/MigrateTestBase.php @@ -90,14 +90,14 @@ private function createMigrationConnection() { } $connection_info = Database::getConnectionInfo('default'); foreach ($connection_info as $target => $value) { - $prefix = is_array($value['prefix']) ? $value['prefix']['default'] : $value['prefix']; + $prefix = $value['prefix']; // Simpletest uses 7 character prefixes at most so this can't cause // collisions. - $connection_info[$target]['prefix']['default'] = $prefix . '0'; + $connection_info[$target]['prefix'] = $prefix . '0'; // Add the original simpletest prefix so SQLite can attach its database. // @see \Drupal\Core\Database\Driver\sqlite\Connection::init() - $connection_info[$target]['prefix'][$value['prefix']['default']] = $value['prefix']['default']; + $connection_info[$target]['extra_prefix'][$prefix] = $prefix; } Database::addConnectionInfo('migrate', 'default', $connection_info['default']); } diff --git a/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php index 51d8a3eb6154601d029b49d8aeec871a774ed3b3..b3be1a339addd1d1981e961c03a356619efca835 100644 --- a/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php +++ b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php @@ -135,14 +135,14 @@ public function testGetDefinitions() { } $connection_info = Database::getConnectionInfo('default'); foreach ($connection_info as $target => $value) { - $prefix = is_array($value['prefix']) ? $value['prefix']['default'] : $value['prefix']; + $prefix = $value['prefix']; // Simpletest uses 7 character prefixes at most so this can't cause // collisions. - $connection_info[$target]['prefix']['default'] = $prefix . '0'; + $connection_info[$target]['prefix'] = $prefix . '0'; // Add the original simpletest prefix so SQLite can attach its database. // @see \Drupal\Core\Database\Driver\sqlite\Connection::init() - $connection_info[$target]['prefix'][$value['prefix']['default']] = $value['prefix']['default']; + $connection_info[$target]['extra_prefix'][$prefix] = $prefix; } Database::addConnectionInfo('migrate', 'default', $connection_info['default']); diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php index cb9eeb21dd303802d1787e37082e2bd284b41551..9da21be807cc6ac6e4b2ff85000f361209f3c8c8 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php @@ -107,7 +107,7 @@ protected function createMigrationConnection() { $connection_info['prefix'] = ''; } else { - $prefix = is_array($connection_info['prefix']) ? $connection_info['prefix']['default'] : $connection_info['prefix']; + $prefix = $connection_info['prefix']; // Simpletest uses fixed length prefixes. Create a new prefix for the // source database. Adding to the end of the prefix ensures that // \Drupal\simpletest\TestBase::restoreEnvironment() will remove the @@ -295,7 +295,6 @@ protected function getCredentials() { $connection_options = $this->sourceDatabase->getConnectionOptions(); $version = $this->getLegacyDrupalVersion($this->sourceDatabase); $driver = $connection_options['driver']; - $connection_options['prefix'] = $connection_options['prefix']['default']; // Use the driver connection form to get the correct options out of the // database settings. This supports all of the databases we test against. diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/FilePathTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/FilePathTest.php index db4848146239102ea9b1d3c1d331121c207f75ae..c5c80c3414a931d68af131439e97d08dc4905a50 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/FilePathTest.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/FilePathTest.php @@ -119,7 +119,6 @@ public function testFilePath(string $file_private_path, string $file_public_path $connection_options = $this->sourceDatabase->getConnectionOptions(); $driver = $connection_options['driver']; - $connection_options['prefix'] = $connection_options['prefix']['default']; // Use the driver connection form to get the correct options out of the // database settings. This supports all of the databases we test against. diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 0e74eda76d01b6c04dfe98912bbb300b475237c2..e19a96853d9375b739bf1a385e16cca406c837a4 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -390,6 +390,18 @@ function system_requirements($phase) { } } + // Verify there are no database entries in settings.php with table prefix in + // array format. + if ($phase === 'runtime' || $phase === 'update') { + if (_system_check_array_table_prefixes(\Drupal::getContainer()->getParameter('app.root'), \Drupal::getContainer()->getParameter('site.path')) === TRUE) { + $requirements['database_table_prefixes'] = [ + 'title' => t('Database table prefixes'), + 'value' => t("There is at least one database entry in the \$database array in settings.php that has a 'prefix' value in the format of an array. Per-table prefixes are no longer supported. Change your settings.php file to ensure the value of every 'prefix' entry is a single string."), + 'severity' => REQUIREMENT_WARNING, + ]; + } + } + if ($phase == 'install' || $phase == 'update') { // Test for PDO (database). $requirements['database_extensions'] = [ @@ -1509,3 +1521,23 @@ function _system_advisories_requirements(array &$requirements): void { } } } + +/** + * Checks if there are 'prefix' entries in array format for tables. + */ +function _system_check_array_table_prefixes($app_root, $site_path) { + if (is_readable($app_root . '/' . $site_path . '/settings.php')) { + include $app_root . '/' . $site_path . '/settings.php'; + } + if (empty($databases)) { + return FALSE; + } + foreach ($databases as $database) { + foreach ($database as $target) { + if (isset($target['prefix']) && is_array($target['prefix'])) { + return TRUE; + } + } + } + return FALSE; +} diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index dfafe4be63284ea63f13735e2c3d308fbf534be5..40ed2b3f2f4020448f0d6aadcb760158fad0252e 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -644,9 +644,7 @@ function simpletest_script_setup_database($new = FALSE) { $databases['test-runner']['default'] = [ 'driver' => 'sqlite', 'database' => $sqlite, - 'prefix' => [ - 'default' => '', - ], + 'prefix' => '', ]; // Create the test runner SQLite database, unless it exists already. if ($new && !file_exists($sqlite)) { diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerWithTablePrefixArrayTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerWithTablePrefixArrayTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ca645e95a7bf031f26f3912af4eaa32dfd00ba1f --- /dev/null +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerWithTablePrefixArrayTest.php @@ -0,0 +1,41 @@ +<?php + +namespace Drupal\FunctionalTests\Installer; + +/** + * Tests the interactive installer with deprecated table prefix array. + * + * @group Installer + */ +class InstallerWithTablePrefixArrayTest extends InstallerTestBase { + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * Ensures that the status report raises the warning after installation. + */ + public function testInstall(): void { + $this->drupalGet('admin/reports/status'); + $this->assertSession()->pageTextNotContains("There is at least one database entry in the \$database array in settings.php that has a 'prefix' value in the format of an array. Per-table prefixes are no longer supported."); + + // Add a database with a multi-entry 'prefix' array. + $settings['databases']['test_fu']['default'] = (object) [ + 'value' => [ + 'database' => 'drupal_db', + 'prefix' => ['default' => 'foo', 'other_table' => 'qux'], + 'host' => 'localhost', + 'namespace' => 'Drupal\Core\Database\Driver\sqlite', + 'driver' => 'sqlite', + ], + 'required' => TRUE, + ]; + $this->writeSettings($settings); + + $this->drupalGet('admin/reports/status'); + $this->assertSession()->pageTextContains("There is at least one database entry in the \$database array in settings.php that has a 'prefix' value in the format of an array. Per-table prefixes are no longer supported."); + } + +} diff --git a/core/tests/Drupal/KernelTests/Core/Database/ConnectionTest.php b/core/tests/Drupal/KernelTests/Core/Database/ConnectionTest.php index 4d7f74feaf2c8b8bf02f0c88d2d3e3d3c49162ef..570146fc10da67be1efeb025711b504c83de093b 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/ConnectionTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/ConnectionTest.php @@ -165,6 +165,43 @@ public function testPDOStatementQueryDeprecation(): void { $this->assertNotNull($db->query($stmt->getClientStatement())); } + /** + * Tests per-table prefix connection option. + */ + public function testPerTablePrefixOption() { + $connection_info = Database::getConnectionInfo('default'); + $new_connection_info = $connection_info['default']; + $new_connection_info['prefix'] = [ + 'default' => $connection_info['default']['prefix'], + 'test_table' => $connection_info['default']['prefix'] . '_bar', + ]; + Database::addConnectionInfo('default', 'foo', $new_connection_info); + $foo_connection = Database::getConnection('foo', 'default'); + $this->assertInstanceOf(Connection::class, $foo_connection); + $this->assertIsString($foo_connection->getConnectionOptions()['prefix']); + $this->assertSame($connection_info['default']['prefix'], $foo_connection->getConnectionOptions()['prefix']); + $this->assertSame([ + 'test_table' => $connection_info['default']['prefix'] . '_bar', + ], $foo_connection->getConnectionOptions()['extra_prefix']); + } + + /** + * Tests the prefix connection option in array form. + */ + public function testPrefixArrayOption() { + $connection_info = Database::getConnectionInfo('default'); + $new_connection_info = $connection_info['default']; + $new_connection_info['prefix'] = [ + 'default' => $connection_info['default']['prefix'], + ]; + Database::addConnectionInfo('default', 'foo', $new_connection_info); + $foo_connection = Database::getConnection('foo', 'default'); + $this->assertInstanceOf(Connection::class, $foo_connection); + $this->assertIsString($foo_connection->getConnectionOptions()['prefix']); + $this->assertSame($connection_info['default']['prefix'], $foo_connection->getConnectionOptions()['prefix']); + $this->assertArrayNotHasKey('extra_prefix', $foo_connection->getConnectionOptions()); + } + /** * Ensure that you cannot execute multiple statements on MySQL. */ diff --git a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php index 0b163a2405b1aa5cdcbd5d368ec1296a4f915de4..eb8ea41d37640ad07449fe41c51729c4ef79918e 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php @@ -1204,7 +1204,10 @@ public function testFindTables() { // Add per-table prefix to the second table. $new_connection_info = $connection_info['default']; - $new_connection_info['prefix']['test_2_table'] = $new_connection_info['prefix']['default'] . '_shared_'; + $new_connection_info['prefix'] = [ + 'default' => $connection_info['default']['prefix'], + 'test_2_table' => $connection_info['default']['prefix'] . '_shared_', + ]; Database::addConnectionInfo('test', 'default', $new_connection_info); Database::setActiveConnection('test'); $test_schema = Database::getConnection()->schema(); diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index 0c379b9322b6fcfe257c7805c1edbe23058d040d..54a6b1af783e93222e0f5956f6b9e9c5cc7db8f8 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -466,9 +466,7 @@ protected function getDatabaseConnectionInfo() { foreach ($connection_info as $target => $value) { // Replace the full table prefix definition to ensure that no table // prefixes of the test runner leak into the test. - $connection_info[$target]['prefix'] = [ - 'default' => $this->databasePrefix, - ]; + $connection_info[$target]['prefix'] = $this->databasePrefix; } } return $connection_info; @@ -646,9 +644,9 @@ protected function tearDown() { // Remove all prefixed tables. $original_connection_info = Database::getConnectionInfo('simpletest_original_default'); - $original_prefix = $original_connection_info['default']['prefix']['default'] ?? NULL; + $original_prefix = $original_connection_info['default']['prefix'] ?? NULL; $test_connection_info = Database::getConnectionInfo('default'); - $test_prefix = $test_connection_info['default']['prefix']['default'] ?? NULL; + $test_prefix = $test_connection_info['default']['prefix'] ?? NULL; if ($original_prefix != $test_prefix) { $tables = Database::getConnection()->schema()->findTables('%'); foreach ($tables as $table) { diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php index 9339fbfe857b170b7b1ac1f5abc307ce5ea2e766..9c0120394a6f9b8079b341cd816b72ab2aa01ca5 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php +++ b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php @@ -56,7 +56,7 @@ public function testBootEnvironment() { */ public function testGetDatabaseConnectionInfoWithOutManualSetDbUrl() { $options = $this->container->get('database')->getConnectionOptions(); - $this->assertSame($this->databasePrefix, $options['prefix']['default']); + $this->assertSame($this->databasePrefix, $options['prefix']); } /** diff --git a/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php b/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php index 7a5ed59072e6ff8a25da634ba781b184a9b2b9be..0eff01cedf1aced097ad69461d907ecbd0ec2b6e 100644 --- a/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php +++ b/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php @@ -81,7 +81,7 @@ protected function tearDown(TestDatabase $test_database, $db_url): void { // Connect to the test database. $root = dirname(__DIR__, 5); $database = Database::convertDbUrlToConnectionInfo($db_url, $root); - $database['prefix'] = ['default' => $test_database->getDatabasePrefix()]; + $database['prefix'] = $test_database->getDatabasePrefix(); Database::addConnectionInfo(__CLASS__, 'default', $database); // Remove all the tables. diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index 1855e15773600294f701c990a50bba53060c12d8..9e5376eb4a53548b976177367f9c04e3ef7f3698 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -424,9 +424,9 @@ public static function filePreDeleteCallback($path) { protected function cleanupEnvironment() { // Remove all prefixed tables. $original_connection_info = Database::getConnectionInfo('simpletest_original_default'); - $original_prefix = $original_connection_info['default']['prefix']['default']; + $original_prefix = $original_connection_info['default']['prefix']; $test_connection_info = Database::getConnectionInfo('default'); - $test_prefix = $test_connection_info['default']['prefix']['default']; + $test_prefix = $test_connection_info['default']['prefix']; if ($original_prefix != $test_prefix) { $tables = Database::getConnection()->schema()->findTables('%'); foreach ($tables as $table) { diff --git a/core/tests/Drupal/Tests/Core/Database/ConditionTest.php b/core/tests/Drupal/Tests/Core/Database/ConditionTest.php index 6f0d29d978385ee0070f80bad5133e99af91ca86..05b65b5f7d67961a857d28a32c1c78f12dd1752a 100644 --- a/core/tests/Drupal/Tests/Core/Database/ConditionTest.php +++ b/core/tests/Drupal/Tests/Core/Database/ConditionTest.php @@ -194,7 +194,7 @@ public function testContribCondition() { class_alias('MockCondition', $mocked_namespace); $options['namespace'] = $contrib_namespace; - $options['prefix']['default'] = ''; + $options['prefix'] = ''; $mockPdo = $this->createMock(StubPDO::class); diff --git a/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php b/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php index a60923b15a1892f4c51e20094518c1567cec5c3e..4376165d3742210b06ca987d566ec82233845481 100644 --- a/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php +++ b/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php @@ -75,6 +75,7 @@ public function testPrefixRoundTrip($expected, $prefix_info) { * - Expected result. * - Table prefix. * - Query to be prefixed. + * - Quote identifier. */ public function providerTestPrefixTables() { return [ @@ -85,23 +86,23 @@ public function providerTestPrefixTables() { ['', ''], ], [ - 'SELECT * FROM "first_table" JOIN "second"."thingie"', - [ - 'table' => 'first_', - 'thingie' => 'second.', - ], - 'SELECT * FROM {table} JOIN {thingie}', + 'SELECT * FROM "test_table"', + 'test_', + 'SELECT * FROM {table}', + ['"', '"'], ], [ - 'SELECT * FROM [first_table] JOIN [second].[thingie]', - [ - 'table' => 'first_', - 'thingie' => 'second.', - ], - 'SELECT * FROM {table} JOIN {thingie}', + "SELECT * FROM 'test_table'", + 'test_', + 'SELECT * FROM {table}', + ["'", "'"], + ], + [ + "SELECT * FROM [test_table]", + 'test_', + 'SELECT * FROM {table}', ['[', ']'], ], - ]; } diff --git a/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php b/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php index fc2ae36f31bedff753de82fd5a69aa7445bf5b81..2dd58125f7fda01d2fc2edbb29955ed36b28d30e 100644 --- a/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php +++ b/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php @@ -96,9 +96,7 @@ public function providerConvertDbUrlToConnectionInfo() { 'password' => 'test_pass', 'host' => 'test_host', 'database' => 'test_database', - 'prefix' => [ - 'default' => 'bar', - ], + 'prefix' => 'bar', 'port' => 3306, 'namespace' => 'Drupal\Core\Database\Driver\mysql', ], @@ -110,9 +108,7 @@ public function providerConvertDbUrlToConnectionInfo() { 'driver' => 'sqlite', 'host' => 'localhost', 'database' => '/var/www/d8/test_database', - 'prefix' => [ - 'default' => 'foo', - ], + 'prefix' => 'foo', 'namespace' => 'Drupal\Core\Database\Driver\sqlite', ], ], @@ -149,9 +145,7 @@ public function providerConvertDbUrlToConnectionInfo() { 'password' => 'test_pass', 'host' => 'test_host', 'database' => 'test_database', - 'prefix' => [ - 'default' => 'bar', - ], + 'prefix' => 'bar', 'port' => 3306, 'namespace' => 'Drupal\driver_test\Driver\Database\DrivertestMysql', 'autoload' => 'core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestMysql/', @@ -180,9 +174,7 @@ public function providerConvertDbUrlToConnectionInfo() { 'password' => 'test_pass', 'host' => 'test_host', 'database' => 'test_database', - 'prefix' => [ - 'default' => 'bar', - ], + 'prefix' => 'bar', 'port' => 5432, 'namespace' => 'Drupal\driver_test\Driver\Database\DrivertestPgsql', 'autoload' => 'core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestPgsql/', diff --git a/core/tests/Drupal/Tests/Scripts/TestSiteApplicationTest.php b/core/tests/Drupal/Tests/Scripts/TestSiteApplicationTest.php index 029830ac51250efe0011e7b6b2c03fe685e9d42a..a312bb1458ea07da6685518ca1cec8ba10674457 100644 --- a/core/tests/Drupal/Tests/Scripts/TestSiteApplicationTest.php +++ b/core/tests/Drupal/Tests/Scripts/TestSiteApplicationTest.php @@ -318,7 +318,7 @@ public function testUserLogin() { */ protected function addTestDatabase($db_prefix) { $database = Database::convertDbUrlToConnectionInfo(getenv('SIMPLETEST_DB'), $this->root); - $database['prefix'] = ['default' => $db_prefix]; + $database['prefix'] = $db_prefix; $target = __CLASS__ . $db_prefix; Database::addConnectionInfo($target, 'default', $database); return $target; diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 64c749d4d012bd76018457db99d0e32e6ea45789..718890224b488ef2ded4b4da4ba6fcc034daceab 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -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