diff --git a/core/lib/Drupal/Core/Command/DbDumpCommand.php b/core/lib/Drupal/Core/Command/DbDumpCommand.php index 337fd7dd51..a260fff8a9 100644 --- a/core/lib/Drupal/Core/Command/DbDumpCommand.php +++ b/core/lib/Drupal/Core/Command/DbDumpCommand.php @@ -259,8 +259,12 @@ protected function getTableCollation(Connection $connection, $table, &$definitio $query = $connection->query("SHOW TABLE STATUS LIKE '{" . $table . "}'"); $data = $query->fetchAssoc(); + // Map the collation to a character set. For example, 'utf8mb4_general_ci' + // (MySQL 5) or 'utf8mb4_0900_ai_ci' (MySQL 8) will be mapped to 'utf8mb4'. + list($charset,) = explode('_', $data['Collation'], 2); + // Set `mysql_character_set`. This will be ignored by other backends. - $definition['mysql_character_set'] = str_replace(['_general_ci', '_0900_ai_ci'], '', $data['Collation']); + $definition['mysql_character_set'] = $charset; } /** diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php index 2286f0beff..e681f7e178 100644 --- a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php +++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php @@ -160,7 +160,8 @@ public static function open(array &$connection_options = []) { // 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. + // 'utf8mb4_general_ci' (MySQL 5) or 'utf8mb4_0900_ai_ci' (MySQL 8) for + // utf8mb4. if (!empty($connection_options['collation'])) { $pdo->exec('SET NAMES ' . $charset . ' COLLATE ' . $connection_options['collation']); } diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php b/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php index cd1f69b40a..3d397c5275 100644 --- a/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php +++ b/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php @@ -44,8 +44,8 @@ public function __toString() { // 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 = array_map(function ($field) { + return $this->connection->escapeField($field); }, $insert_fields); // If we're selecting from a SelectQuery, finish building the query and diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php index b742c2ce22..cd0e600f57 100644 --- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php +++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php @@ -121,8 +121,9 @@ protected function createTableSql($name, $table) { $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. + // 'utf8mb4_general_ci' (MySQL 5) or 'utf8mb4_0900_ai_ci' (MySQL 8) for + // utf8mb4. If an alternate collation has been set, it needs to be + // explicitly specified. // @see \Drupal\Core\Database\Driver\mysql\Schema if (!empty($info['collation'])) { $sql .= ' COLLATE ' . $info['collation']; diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Upsert.php b/core/lib/Drupal/Core/Database/Driver/mysql/Upsert.php index 6c1af1e812..8eda775c0a 100644 --- a/core/lib/Drupal/Core/Database/Driver/mysql/Upsert.php +++ b/core/lib/Drupal/Core/Database/Driver/mysql/Upsert.php @@ -18,6 +18,9 @@ public function __toString() { // Default fields are always placed first for consistency. $insert_fields = array_merge($this->defaultFields, $this->insertFields); + $insert_fields = array_map(function ($field) { + return $this->connection->escapeField($field); + }, $insert_fields); $query = $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES '; diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php index a9ff4b136d..9a21aeaf7c 100644 --- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php +++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php @@ -219,7 +219,7 @@ public function addField($field, $type, $langcode) { // field no other value than 0 makes sense. if (is_numeric($next)) { if ($next > 0) { - $this->sqlQuery->condition('1 <> 1'); + $this->sqlQuery->where('1 <> 1'); } $key++; $next = $specifiers[$key + 1]; diff --git a/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php b/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php index d06a81c41e..b2887afb05 100644 --- a/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php +++ b/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php @@ -242,7 +242,7 @@ public function entityQueryAlter(SelectInterface $query) { $value_part->condition('anonymous_name', $condition['value'], $condition['operator']); $value_part->compile($this->connection, $query); $or->condition((new Condition('AND')) - ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + [':anonymous_name' => \Drupal::config('user.settings')->get('anonymous')]) + ->where(str_replace($query->escapeField('anonymous_name'), ':anonymous_name', (string) $value_part), $value_part->arguments() + [':anonymous_name' => \Drupal::config('user.settings')->get('anonymous')]) ->condition('base_table.uid', 0) ); $query->condition($or); diff --git a/core/modules/views_ui/src/Tests/PreviewTest.php b/core/modules/views_ui/src/Tests/PreviewTest.php index 657c8704fc..c5e8e77f10 100644 --- a/core/modules/views_ui/src/Tests/PreviewTest.php +++ b/core/modules/views_ui/src/Tests/PreviewTest.php @@ -3,6 +3,8 @@ namespace Drupal\views_ui\Tests; use Drupal\Component\Serialization\Json; +use Drupal\Component\Utility\Html; +use Drupal\Core\Database\Database; use Drupal\Core\EventSubscriber\MainContentViewSubscriber; /** @@ -105,7 +107,11 @@ public function testPreviewUI() { $this->assertText(t('Query execute time')); $this->assertText(t('View render time')); $this->assertRaw('Query'); - $this->assertText("SELECT views_test_data.name AS views_test_data_name\nFROM \n{views_test_data} views_test_data\nWHERE (views_test_data.id = '100')"); + $conn = Database::getConnection(); + // Build up the query string using the database's escaping methods. Views + // has a very strange strategy here. + $query = "SELECT views_test_data." . $conn->escapeField('name') . " AS " . $conn->escapeAlias('views_test_data_name') . "\nFROM \n{views_test_data} views_test_data\nWHERE (views_test_data.id = '100')"; + $this->assertText(Html::escape($query)); // Test that the statistics and query are rendered above the preview. $this->assertTrue(strpos($this->getRawContent(), 'views-query-info') < strpos($this->getRawContent(), 'view-test-preview'), 'Statistics shown above the preview.'); diff --git a/core/modules/views_ui/tests/src/Functional/SettingsTest.php b/core/modules/views_ui/tests/src/Functional/SettingsTest.php index 1ac98c6e63..61c7053d75 100644 --- a/core/modules/views_ui/tests/src/Functional/SettingsTest.php +++ b/core/modules/views_ui/tests/src/Functional/SettingsTest.php @@ -117,7 +117,7 @@ public function testEditUI() { $xpath = $this->xpath('//div[@class="views-query-info"]//pre'); $this->assertEqual(count($xpath), 1, 'The views sql is shown.'); $this->assertFalse(strpos($xpath[0]->getText(), 'db_condition_placeholder') !== FALSE, 'No placeholders are shown in the views sql.'); - $this->assertTrue(strpos($xpath[0]->getText(), "node_field_data.status = '1'") !== FALSE, 'The placeholders in the views sql is replace by the actual value.'); + $this->assertTrue(strpos($xpath[0]->getText(), $this->getDatabaseConnection()->escapeField('node_field_data.status') . " = '1'") !== FALSE, 'The placeholders in the views sql is replace by the actual value.'); // Test the advanced settings form. diff --git a/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php b/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php index 2082e8e074..d6b0f8dd80 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php @@ -209,9 +209,9 @@ public function testSpecialColumnInsert() { ->fields('test_special_columns', ['offset', 'function']) ->condition('test_special_columns.function', 'foobar') ->execute(); - $records = $result->fetch(); - $this->assertSame('Offset value 2', $records->offset); - $this->assertSame('foobar', $records->function); + $record = $result->fetch(); + $this->assertSame('Offset value 2', $record->offset); + $this->assertSame('foobar', $record->function); } }