- πΊπΈUnited States smustgrave
Should this be reopened based on the last few comments?
- π¦πΊAustralia acbramley
Doesn't seem like a bug to me, please correct me and provide some more info if not. This has come up in BSI a few times.
- Status changed to Active
26 days ago 3:07pm 12 August 2024 - π¬π§United Kingdom joachim
The docs say:
* When a bundle, field or field storage is deleted, it is not practical to * perform those operations immediately on every affected entity in a single * page request; there could be thousands or millions of them. Instead, the * appropriate field data items, fields, and/or field storages are marked as * deleted so that subsequent load or query operations will not return them. * Later, a separate process cleans up, or "purges", the marked-as-deleted data * by going through the three-step process described above and, finally, * removing deleted field storage and field records.
This situation can be created without field module being present:
1 define an entity type which uses bundles with a config entity
2 define a multi-valued base field on the entity type. This will therefore get a field table
3 create a bundle entity
4 create some entities
5 delete the bundle entityI can make a kernel test which sets this up, but I think this is actually showing a deeper problem -- nothing is going to mark the field table's items as 'deleted' anyway, since SqlContentEntityStorage and FieldDefinitionListener are working with field storage and field definitions.
<?php declare(strict_types=1); namespace Drupal\KernelTests\Core\Field; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\KernelTests\KernelTestBase; /** * Tests TODO. * * @group Entity */ class BulkDeleteTest extends KernelTestBase { /** * {@inheritdoc} */ protected static $modules = [ 'entity_test', 'system', 'user', ]; /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * {@inheritdoc} */ protected function setUp(): void { parent::setUp(); $this->entityTypeManager = $this->container->get('entity_type.manager'); $definitions = []; $definitions['multi'] = BaseFieldDefinition::create('string') ->setLabel('Multiple') ->setCardinality(2); $this->container->get('state')->set('entity_test.additional_base_field_definitions', $definitions); $this->entityTypeManager->clearCachedDefinitions(); $this->installEntitySchema('entity_test'); $this->installEntitySchema('entity_test_bundle'); } public function testDeleteMultiBaseFieldTables() { // Create a bundle. $alpha = $this->entityTypeManager->getStorage('entity_test_bundle')->create([ 'id' => 'alpha', ]); $alpha->save(); // Create an entity. $storage = $this->entityTypeManager->getStorage('entity_test'); $entity = $storage->create([ 'type' => 'alpha', 'name' => 'One', 'multi' => [ 'one', 'two', ], ]); $entity->save(); $database = \Drupal::database(); $query = $database->query("SELECT count(*) FROM {entity_test__multi}"); $field_table_row_count = $query->fetchField(); $this->assertEquals(2, $field_table_row_count); $alpha->delete(); // What should the entity and field tables contain now? $query = $database->query("SELECT * FROM {entity_test}"); $rows = $query->fetchAll(); dump($rows); $query = $database->query("SELECT * FROM {entity_test__multi}"); $rows = $query->fetchAll(); dump($rows); } }
Another reason for moving field_purge_batch() to core-Field though is that all of the calls it makes are to core-Field:
/** @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface $deleted_fields_repository */ $deleted_fields_repository = \Drupal::service('entity_field.deleted_fields_repository');
apart from field_purge_field_storage() which lives in the same file.