drush-ops / drush

Drush is a command-line shell and scripting interface for Drupal, a veritable Swiss Army knife designed to make life easier for those who spend their working hours hacking away at the command prompt.
https://www.drush.org
2.33k stars 1.08k forks source link

Add an action to create missing field_deleted_data_* #5122

Open pylandure-cobredia opened 2 years ago

pylandure-cobredia commented 2 years ago

When running drupal cron tasks, the following error can appear in the logs:

Drupal\Core\Database\DatabaseExceptionWrapper:
SQLSTATE[42S02]: Base table or view not found:
1146 Table 'field_deleted_data_1c89727af8' doesn't exist:
SELECT DISTINCT t.entity_id AS entity_id
FROM {field_deleted_data_1c89727af8} t
WHERE  (bundle = :db_condition_placeholder_0)
LIMIT 50 OFFSET 0; Array
(
    [:db_condition_placeholder_0] => video
)
in
Drupal\Core\Entity\Sql\SqlContentEntityStorage->readFieldItemsToPurge()

This is due to missing field_deleted_data_* tables. It is often the result of a overeager database manipulation by an inexperienced administrator.

The solution to this error is to create the missing table, as described by the reply to How to make Drupal 8 forget an old deleted field?.

But when many field_deleted_data_*tables have been dropped, this can be very fastidious, since it has to be done one table at a time, when the error appear.

I created a imperfect script to create the missing tables:

vendor/bin/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);
}
'

I would like for script to be cleaned-up and added as a drush command to help users fix the missing "field_deleteddata" errors.

The table_name computation is based on the code found at the beginning of the SqlContentEntityStorage::readFieldItemsToPurge() method.

I'm a newbie at Drupal, so i can't contribute more than this to the script.

weitzman commented 2 years ago

This seems useful. I have a site with this problem. Thanks for sharing your code.