protected function SqlContentEntityStorageSchema::updateSharedTableSchema

protected SqlContentEntityStorageSchema::updateSharedTableSchema(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original)

Updates the schema for a field stored in a shared table.

Parameters

\Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition: The storage definition of the field being updated.

\Drupal\Core\Field\FieldStorageDefinitionInterface $original: The original storage definition; i.e., the definition before the update.

Throws

\Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException Thrown when the update to the field is forbidden.

\Exception Rethrown exception if the table recreation fails.

File

core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php, line 1350

Class

SqlContentEntityStorageSchema
Defines a schema handler that supports revisionable, translatable entities.

Namespace

Drupal\Core\Entity\Sql

Code

protected function updateSharedTableSchema(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original) {
  if (!$this->storage->countFieldData($original, TRUE)) {
    if ($this->database->supportsTransactionalDDL()) {
      // If the database supports transactional DDL, we can go ahead and rely
      // on it. If not, we will have to rollback manually if something fails.
      $transaction = $this->database->startTransaction();
    }
    try {
      // Since there is no data we may be switching from a dedicated table
      // to a schema table schema, hence we should use the proper API.
      $this->performFieldSchemaOperation('delete', $original);
      $this->performFieldSchemaOperation('create', $storage_definition);
    }
    catch (\Exception $e) {
      if ($this->database->supportsTransactionalDDL()) {
        $transaction->rollback();
      }
      else {
        // Recreate original schema.
        $this->createSharedTableSchema($original);
      }
      throw $e;
    }
  }
  else {
    if ($this->hasColumnChanges($storage_definition, $original)) {
      throw new FieldStorageDefinitionUpdateForbiddenException('The SQL storage cannot change the schema for an existing field (' . $storage_definition->getName() . ' in ' . $storage_definition->getTargetEntityTypeId() . ' entity) with data.');
    }

    $updated_field_name = $storage_definition->getName();
    $table_mapping = $this->storage->getTableMapping();
    $column_names = $table_mapping->getColumnNames($updated_field_name);
    $schema_handler = $this->database->schema();

    // Iterate over the mapped table to find the ones that host the deleted
    // field schema.
    $original_schema = $this->loadFieldSchemaData($original);
    $schema = array();
    foreach ($table_mapping->getTableNames() as $table_name) {
      foreach ($table_mapping->getFieldNames($table_name) as $field_name) {
        if ($field_name == $updated_field_name) {
          $schema[$table_name] = $this->getSharedTableFieldSchema($storage_definition, $table_name, $column_names);

          // Handle NOT NULL constraints.
          foreach ($schema[$table_name]['fields'] as $column_name => $specifier) {
            $not_null = !empty($specifier['not null']);
            $original_not_null = !empty($original_schema[$table_name]['fields'][$column_name]['not null']);
            if ($not_null !== $original_not_null) {
              if ($not_null && $this->hasNullFieldPropertyData($table_name, $column_name)) {
                throw new EntityStorageException("The $column_name column cannot have NOT NULL constraints as it holds NULL values.");
              }
              $column_schema = $original_schema[$table_name]['fields'][$column_name];
              $column_schema['not null'] = $not_null;
              $schema_handler->changeField($table_name, $field_name, $field_name, $column_schema);
            }
          }

          // Drop original indexes and unique keys.
          if (!empty($original_schema[$table_name]['indexes'])) {
            foreach ($original_schema[$table_name]['indexes'] as $name => $specifier) {
              $schema_handler->dropIndex($table_name, $name);
            }
          }
          if (!empty($original_schema[$table_name]['unique keys'])) {
            foreach ($original_schema[$table_name]['unique keys'] as $name => $specifier) {
              $schema_handler->dropUniqueKey($table_name, $name);
            }
          }
          // Create new indexes and unique keys.
          if (!empty($schema[$table_name]['indexes'])) {
            foreach ($schema[$table_name]['indexes'] as $name => $specifier) {
              // Check if the index exists because it might already have been
              // created as part of the earlier entity type update event.
              $this->addIndex($table_name, $name, $specifier, $schema[$table_name]);

            }
          }
          if (!empty($schema[$table_name]['unique keys'])) {
            foreach ($schema[$table_name]['unique keys'] as $name => $specifier) {
              $schema_handler->addUniqueKey($table_name, $name, $specifier);
            }
          }
          // After deleting the field schema skip to the next table.
          break;
        }
      }
    }
    $this->saveFieldSchemaData($storage_definition, $schema);
  }
}

© 2001–2016 by the original authors
Licensed under the GNU General Public License, version 2 and later.
Drupal is a registered trademark of Dries Buytaert.
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!Sql!SqlContentEntityStorageSchema.php/function/SqlContentEntityStorageSchema::updateSharedTableSchema/8.1.x