diff -u b/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php --- b/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -42,6 +42,13 @@ protected $checksumProvider; /** + * The transliteration service. + * + * @var \Drupal\Component\Transliteration\TransliterationInterface + */ + protected $transliteration; + + /** * Constructs a DatabaseBackend object. * * @param \Drupal\Core\Database\Connection $connection @@ -419,20 +426,36 @@ * The passed in cache ID. * * @return string - * A cache ID that is at most 255 characters long. + * An ASCII-encoded cache ID that is at most 255 characters long. */ protected function normalizeCid($cid) { - // Nothing to do if the ID length is 255 characters or less. - if (strlen($cid) <= 255) { + // Nothing to do if the ID is a US ASCII string of 255 characters or less. + $cid_is_ascii = mb_check_encoding($cid, 'ASCII'); + if (strlen($cid) <= 255 && $cid_is_ascii) { return $cid; } // Return a string that uses as much as possible of the original cache ID // with the hash appended. $hash = Crypt::hashBase64($cid); + if (!$cid_is_ascii) { + $cid = $this->transliteration()->transliterate($cid); + } return substr($cid, 0, 255 - strlen($hash)) . $hash; } /** + * Wraps the transliteration service. + * + * @return \Drupal\Component\Transliteration\TransliterationInterface + */ + protected function transliteration() { + if (!$this->transliteration) { + $this->transliteration = \Drupal::transliteration(); + } + return $this->transliteration; + } + + /** * Defines the schema for the {cache_*} bin tables. */ public function schemaDefinition() { diff -u b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php --- b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php +++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php @@ -364,6 +364,7 @@ // $map does not use drupal_static as its value never changes. static $map = array( 'varchar_ascii:normal' => 'varchar', + 'varchar:normal' => 'varchar', 'char:normal' => 'character', only in patch2: unchanged: --- a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php +++ b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php @@ -33,4 +33,24 @@ protected function createCacheBackend($bin) { return new DatabaseBackend($this->container->get('database'), $this->container->get('cache_tags.invalidator.checksum'), $bin); } + /** + * {@inheritdoc} + */ + public function testSetGet() { + parent::testSetGet(); + $backend = $this->getCacheBackend(); + + // Set up a cache ID that is not ASCII and longer than 255 characters so we + // can test cache ID normalization. + $cid_long = str_repeat('愛€', 500); + $cached_value_long = $this->randomMachineName(); + $backend->set($cid_long, $cached_value_long); + $this->assertIdentical($cached_value_long, $backend->get($cid_long)->data, "Backend contains the correct value for long, non-ASCII cache id."); + + $cid_short = '愛1€'; + $cached_value_short = $this->randomMachineName(); + $backend->set($cid_short, $cached_value_short); + $this->assertIdentical($cached_value_short, $backend->get($cid_short)->data, "Backend contains the correct value for short, non-ASCII cache id."); + } + }