Thank you every one for your answers that allowed me to build the following (imperfect) solution.
List deleted fields waiting to be purged:
drush php:eval "var_dump(\Drupal::state()->get('field.storage.deleted'))"
If the result is not an empty array, create the missing field_deleted_data_*
tables:
drush php:eval '$deleted_field_storage_configs = \Drupal::state()->get("field.storage.deleted");
$database = \Drupal::database();
foreach($deleted_field_storage_configs as $field_storage_config) {
$table_name = "field_deleted_data_" . substr(hash("sha256", $field_storage_config->getUniqueStorageIdentifier()), 0, 10);
$sql_query = "CREATE TABLE IF NOT EXISTS `" . $table_name . "` (
`bundle` varchar(128) CHARACTER SET ascii NOT NULL DEFAULT '\'\'',
`deleted` tinyint(4) NOT NULL DEFAULT '\''0'\'',
`entity_id` int(10) unsigned NOT NULL,
`revision_id` int(10) unsigned NOT NULL,
`langcode` varchar(32) CHARACTER SET ascii NOT NULL DEFAULT '\'\'',
`delta` int(10) unsigned NOT NULL,
`content_translation_source_value` varchar(12) CHARACTER SET ascii NOT NULL,
PRIMARY KEY (`entity_id`,`deleted`,`delta`,`langcode`),
KEY `bundle` (`bundle`),
KEY `revision_id` (`revision_id`) );";
$database->query($sql_query);
}
'
Remove the fields:
vendor/bin/drush php-eval 'field_purge_batch(1000);'
Check that no more fields are waiting to be purged:
drush php:eval "var_dump(\Drupal::state()->get('field.storage.deleted'))"
You can now safely remove field_deleted_data_*
tables that are still present in the Drupal database.
To perfect this solution:
I based the table name computation on the code of the SqlContentEntityStorage::readFieldItemsToPurge() method.
The better way to do this would be to find a way to get the SqlContentEntityStorage and field storage definition to have the good version of table name computation:
$storage_definition = $field_definition->getFieldStorageDefinition();
$table_mapping = $this->getTableMapping();
$table_name = $table_mapping->getDedicatedDataTableName($storage_definition, $storage_definition->isDeleted());