When you install a module that changes the field storage definitions and also change the entity type definitions (I do this with Multiversion module), the update process fails with these errors:

Drupal\Core\Database\SchemaObjectDoesNotExistException: Cannot add field entity_test_field_override_revision._deleted: table doesn't exist. in Drupal\Core\Database\Driver\mysql\Schema->addField() (line 328 of .../core/lib/Drupal/Core/Database/Driver/mysql/Schema.php).

or

Drupal\Core\Database\SchemaObjectExistsException: Cannot add field entity_test_field_override._deleted: field already exists. in Drupal\Core\Database\Driver\mysql\Schema->addField() (line 331 of .../core/lib/Drupal/Core/Database/Driver/mysql/Schema.php).

Comments

jeqq’s picture

Issue summary: View changes
berdir’s picture

Status: Active » Postponed (maintainer needs more info)

Yes, it was, are you sure you tested with latest dev snapshot and not a beta?

jeqq’s picture

@Berdir, I tested with latest dev snapshot. Steps to reproduce:

    • Make an entity type revisionable (for non-revisionable entity types we don't have the [entity-type-id]_revision table initially) - set the revision key in hook_entity_type_alter():
      $keys = $entity_type->getKeys();
      $keys['revision'] = 'revision_id';
      $entity_type->set('entity_keys', $keys);
      
    • Add new fields in hook_entity_base_field_info() for the same entity type.
  1. Apply updates with EntityDefinitionUpdateManager::applyUpdates()

In this case firstly we need to update the entity type storage (will create the [entity-type-id]_revision table) and then to create the new fields. At the moment in EntityDefinitionUpdateManager::applyUpdates() the EntityManager::onFieldStorageDefinitionCreate() method is executed before EntityManager::onEntityTypeUpdate() and the [entity-type-id]_revision table doesn't exist.

plach’s picture

Issue tags: +entity storage
jeqq’s picture

This can be reproduced when you make the entity revisionable and add a new revisionable field. I've created a failing test that demonstrates this.

jeqq’s picture

Status: Postponed (maintainer needs more info) » Needs review

Status: Needs review » Needs work

The last submitted patch, 6: 2398689-6-test-add-revisionable-field.patch, failed testing.

jeqq’s picture

Reroll

jeqq’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 9: 2398689-9-test-add-revisionable-field.patch, failed testing.

jeqq’s picture

Status: Needs work » Needs review
StatusFileSize
new6.34 KB

Moved the entity type update before field storage definition creation to ensure that the revision table will be created before revisionable fields.

dixon_’s picture

Title: Applying entity schema updates fail when both field and entity type definitions changes » Follow-up: Applying entity schema updates still fail when both field and entity type definitions changes
Status: Needs review » Needs work

I would almost want to bump this to critical considering that #2342543: Applying entity schema updates fail when both entity type and base field definitions change at the same time was critical and the issue isn't fully resolved yet. But I'll leave it up to someone else to decide on that. I'm changing the title though to make it clear that this closely related to the original issue.

+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
@@ -1076,7 +1076,9 @@ protected function performFieldSchemaOperation($operation, FieldStorageDefinitio
+      if (!$this->database->schema()->tableExists($name)) {
+        $this->database->schema()->createTable($name, $table);
+      }
     }
     $this->saveFieldSchemaData($storage_definition, $schema);
   }
@@ -1109,11 +1111,15 @@ protected function createSharedTableSchema(FieldStorageDefinitionInterface $stor

@@ -1109,11 +1111,15 @@ protected function createSharedTableSchema(FieldStorageDefinitionInterface $stor
           $schema[$table_name] = $this->getSharedTableFieldSchema($storage_definition, $table_name, $column_names);
           if (!$only_save) {
             foreach ($schema[$table_name]['fields'] as $name => $specifier) {
-              $schema_handler->addField($table_name, $name, $specifier);
+              if (!$schema_handler->fieldExists($table_name, $name)) {
+                $schema_handler->addField($table_name, $name, $specifier);
+              }
             }
             if (!empty($schema[$table_name]['indexes'])) {
               foreach ($schema[$table_name]['indexes'] as $name => $specifier) {
-                $schema_handler->addIndex($table_name, $name, $specifier);
+                if (!$schema_handler->indexExists($table_name, $name)) {
+                  $schema_handler->addIndex($table_name, $name, $specifier);
+                }
               }

I think it would be good to add a comment to each of these three sections, saying something like "The table/field/index might already have been created as part of the earlier entity type update event."

+++ b/core/modules/system/src/Tests/Entity/EntityDefinitionTestTrait.php
@@ -101,6 +101,21 @@ protected function addBaseField($type = 'string') {
+      ->setLabel(t('A new base field'))

Let's change the description to "A new revisionable base field"

jeqq’s picture

Status: Needs work » Needs review
StatusFileSize
new6.79 KB

Added comments and fixed the label.

dixon_’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php
@@ -559,4 +559,23 @@ public function testEntityTypeSchemaUpdateAndBaseFieldCreateWithoutData() {
+  /**
+   * Tests updating entity schema and creating a revisionable base field at the same time when there are no existing entities.
+   */
+  public function testEntityTypeSchemaUpdateAndRevisionableBaseFieldCreateWithoutData() {

Minor nit-pick - let's also wrap this comment line at 80 characters.

jeqq’s picture

Status: Needs work » Needs review
StatusFileSize
new7.23 KB

Thanks for the review @dixon_.

dixon_’s picture

Status: Needs review » Reviewed & tested by the community

Thanks @jeqq! IMO this one is ready.

plach’s picture

Status: Reviewed & tested by the community » Needs work

Looks great, thanks, only a couple of minor issues:

  1. +++ b/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php
    @@ -541,7 +541,8 @@ public function testDefinitionEvents() {
    +   * Tests updating entity schema and creating a base field at the same time
    +   * when there are no existing entities.
    
    @@ -559,4 +560,24 @@ public function testEntityTypeSchemaUpdateAndBaseFieldCreateWithoutData() {
    +   * Tests updating entity schema and creating a revisionable base field at the
    +   * same time when there are no existing entities.
    +   */
    

    These need to be a single line shorter than 80 chars. Let's add a one-line intro followed by a blank line and put the rest in a following paragraph if needed.

  2. +++ b/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php
    @@ -559,4 +560,24 @@ public function testEntityTypeSchemaUpdateAndBaseFieldCreateWithoutData() {
    +      $this->pass('Successfully updated entity schema and created revisionable base field at the same time.');
    ...
    +      $this->fail('Successfully updated entity schema and created revisionable base field at the same time.');
    

    Can we use a $message variable to avoid replicating the text?

jeqq’s picture

Status: Needs work » Needs review
StatusFileSize
new7.9 KB
new2.67 KB

Thanks @plach!

jeqq’s picture

jeqq’s picture

plach’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC

plach’s picture

Title: Follow-up: Applying entity schema updates still fail when both field and entity type definitions changes » Follow-up: Applying entity schema updates still fails when both field and entity type definitions changes
alexpott’s picture

Status: Reviewed & tested by the community » Fixed

This issue addresses a major bug and is allowed per https://www.drupal.org/core/beta-changes. Committed d42d61a and pushed to 8.0.x. Thanks!

  • alexpott committed d42d61a on 8.0.x
    Issue #2398689 by jeqq: Follow-up: Applying entity schema updates still...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.