function SqlContentEntityStorageSchema::updateDedicatedTableSchema

Same name in other branches
  1. 8.9.x core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::updateDedicatedTableSchema()
  2. 10 core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::updateDedicatedTableSchema()
  3. 11.x core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::updateDedicatedTableSchema()

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 1727

Class

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

Namespace

Drupal\Core\Entity\Sql

Code

protected function updateDedicatedTableSchema(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original) {
    if (!$this->storage
        ->countFieldData($original, TRUE)) {
        // There is no data. Re-create the tables completely.
        try {
            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();
            }
            // Since there is no data we may be switching from a shared table schema
            // to a dedicated 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()) {
                if (isset($transaction)) {
                    $transaction->rollBack();
                }
            }
            else {
                // Recreate tables.
                $this->performFieldSchemaOperation('create', $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.');
        }
        // There is data, so there are no column changes. Drop all the prior
        // indexes and create all the new ones, except for all the priors that
        // exist unchanged.
        $table_mapping = $this->getTableMapping($this->entityType, [
            $storage_definition,
        ]);
        $table = $table_mapping->getDedicatedDataTableName($original);
        $revision_table = $table_mapping->getDedicatedRevisionTableName($original);
        // Get the field schemas.
        $schema = $storage_definition->getSchema();
        $original_schema = $original->getSchema();
        // Gets the SQL schema for a dedicated tables.
        $actual_schema = $this->getDedicatedTableSchema($storage_definition);
        foreach ($original_schema['indexes'] as $name => $columns) {
            if (!isset($schema['indexes'][$name]) || $columns != $schema['indexes'][$name]) {
                $real_name = $this->getFieldIndexName($storage_definition, $name);
                $this->database
                    ->schema()
                    ->dropIndex($table, $real_name);
                $this->database
                    ->schema()
                    ->dropIndex($revision_table, $real_name);
            }
        }
        $table = $table_mapping->getDedicatedDataTableName($storage_definition);
        $revision_table = $table_mapping->getDedicatedRevisionTableName($storage_definition);
        foreach ($schema['indexes'] as $name => $columns) {
            if (!isset($original_schema['indexes'][$name]) || $columns != $original_schema['indexes'][$name]) {
                $real_name = $this->getFieldIndexName($storage_definition, $name);
                $real_columns = [];
                foreach ($columns as $column_name) {
                    // Indexes can be specified as either a column name or an array with
                    // column name and length. Allow for either case.
                    if (is_array($column_name)) {
                        $real_columns[] = [
                            $table_mapping->getFieldColumnName($storage_definition, $column_name[0]),
                            $column_name[1],
                        ];
                    }
                    else {
                        $real_columns[] = $table_mapping->getFieldColumnName($storage_definition, $column_name);
                    }
                }
                // Check if the index exists because it might already have been
                // created as part of the earlier entity type update event.
                $this->addIndex($table, $real_name, $real_columns, $actual_schema[$table]);
                $this->addIndex($revision_table, $real_name, $real_columns, $actual_schema[$revision_table]);
            }
        }
        $this->saveFieldSchemaData($storage_definition, $this->getDedicatedTableSchema($storage_definition));
    }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.