protected function SqlContentEntityStorageSchema::updateSharedTableSchema in Drupal 9
Same name and namespace in other branches
- 8 core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::updateSharedTableSchema()
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 1816
Class
- SqlContentEntityStorageSchema
- Defines a schema handler that supports revisionable, translatable entities.
Namespace
Drupal\Core\Entity\SqlCode
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
->getTableMapping($this->entityType, [
$storage_definition,
]);
$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 = [];
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, $column_name, $column_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);
}
}