diff -u b/core/lib/Drupal/Core/Cache/CachetagSchema.php b/core/lib/Drupal/Core/Cache/CachetagSchema.php --- b/core/lib/Drupal/Core/Cache/CachetagSchema.php +++ b/core/lib/Drupal/Core/Cache/CachetagSchema.php @@ -9,6 +9,12 @@ use Drupal\Core\Database\SchemaProviderInterface; +/** + * Class providing schema for the {cachetags} table. + * + * One SchemaProviderInterface class can provide only one table but cache works + * with two. + */ class CachetagSchema implements SchemaProviderInterface { /** 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 @@ -409,6 +409,7 @@ if ($this->connection->schema()->tableExists('cachetags')) { throw $e; } + // The table does not exist yet so there are no db tags. $db_tags = array(); } $tag_cache += $db_tags; diff -u b/core/lib/Drupal/Core/Database/Query/Query.php b/core/lib/Drupal/Core/Database/Query/Query.php --- b/core/lib/Drupal/Core/Database/Query/Query.php +++ b/core/lib/Drupal/Core/Database/Query/Query.php @@ -9,7 +9,6 @@ use Drupal\Core\Database\Database; use Drupal\Core\Database\Connection; -use Drupal\Core\Database\SchemaObjectExistsException; use Drupal\Core\Database\SchemaProviderInterface; /** @@ -23,7 +22,9 @@ /** * The base table. * - * @var string + * Can be a Query object for subqueries. + * + * @var string|static */ protected $table; @@ -137,13 +138,8 @@ return $this->execute(); } catch (\Exception $e) { - // Resolve count queries. - $table = $this->table; - while ($table instanceof Query) { - $table = $table->getTable(); - } // If there was an exception, try to create the table. - if ($this->connection->schema()->ensureTableExists($table, $schema_provider)) { + if ($this->connection->schema()->ensureTableExists($this->getTable(), $schema_provider)) { return $this->execute(); } // Some other failure that we can not recover from. @@ -151,8 +147,19 @@ } } + /** + * Returns the base table. + * + * @return string + * The base table. If the base table is a subquery then the base table of + * that query. This was even for count queries the base table is returned. + */ public function getTable() { - return $this->table; + $table = $this->table; + while ($table instanceof Query) { + $table = $table->getTable(); + } + return $table; } /** diff -u b/core/lib/Drupal/Core/Database/SchemaProviderInterface.php b/core/lib/Drupal/Core/Database/SchemaProviderInterface.php --- b/core/lib/Drupal/Core/Database/SchemaProviderInterface.php +++ b/core/lib/Drupal/Core/Database/SchemaProviderInterface.php @@ -22,6 +22,9 @@ * A schema API array. * * @return array + * A schema API array + * + * @see hook_schema() */ public function getSchema(); } diff -u b/core/modules/system/src/Tests/Database/SelectTest.php b/core/modules/system/src/Tests/Database/SelectTest.php --- b/core/modules/system/src/Tests/Database/SelectTest.php +++ b/core/modules/system/src/Tests/Database/SelectTest.php @@ -29,9 +29,9 @@ } /** - * Tests rudimentary SELECT statements. + * Tests rudimentary SELECT statements with table dropping and recreation. */ - function testSimpleSelectWithTableAssert() { + function testSimpleSelectWithEnsuringTable() { db_drop_table('test'); $query = db_select('test'); $query->addField('test', 'name'); only in patch2: unchanged: --- a/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php +++ b/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php @@ -8,6 +8,7 @@ namespace Drupal\system\Tests\Cache; use Drupal\Core\Cache\Cache; +use Drupal\Core\Database\Database; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\simpletest\DrupalUnitTestBase; use Symfony\Component\DependencyInjection\Reference; @@ -48,7 +49,7 @@ public function testTagInvalidations() { $this->assertTrue($bin->get('test'), 'Cache item was set in bin.'); } - $invalidations_before = intval(db_select('cachetags')->fields('cachetags', array('invalidations'))->condition('tag', 'test_tag:2')->execute()->fetchField()); + $this->assertFalse(Database::getConnection()->schema()->tableExists('cachetags')); Cache::invalidateTags(array('test_tag:2')); // Test that cache entry has been invalidated in multiple bins. @@ -59,7 +60,7 @@ public function testTagInvalidations() { // Test that only one tag invalidation has occurred. $invalidations_after = intval(db_select('cachetags')->fields('cachetags', array('invalidations'))->condition('tag', 'test_tag:2')->execute()->fetchField()); - $this->assertEqual($invalidations_after, $invalidations_before + 1, 'Only one addition cache tag invalidation has occurred after invalidating a tag used in multiple bins.'); + $this->assertEqual($invalidations_after, 1, 'Only one addition cache tag invalidation has occurred after invalidating a tag used in multiple bins.'); } public function testTagDeletions() { @@ -72,7 +73,7 @@ public function testTagDeletions() { $this->assertTrue($bin->get('test'), 'Cache item was set in bin.'); } - $deletions_before = intval(db_select('cachetags')->fields('cachetags', array('deletions'))->condition('tag', 'test_tag:2')->execute()->fetchField()); + $this->assertFalse(Database::getConnection()->schema()->tableExists('cachetags')); Cache::deleteTags(array('test_tag:2')); // Test that cache entry has been deleted in multiple bins. @@ -83,7 +84,7 @@ public function testTagDeletions() { // Test that only one tag deletion has occurred. $deletions_after = intval(db_select('cachetags')->fields('cachetags', array('deletions'))->condition('tag', 'test_tag:2')->execute()->fetchField()); - $this->assertEqual($deletions_after, $deletions_before + 1, 'Only one addition cache tag deletion has occurred after deleting a tag used in multiple bins.'); + $this->assertEqual($deletions_after, 1, 'Only one addition cache tag deletion has occurred after deleting a tag used in multiple bins.'); } }