Commit f27fd1f5 authored by alexpott's avatar alexpott

Issue #2337927 by effulgentsia, plach, fago: Fixed...

Issue #2337927 by effulgentsia, plach, fago: Fixed SqlContentEntityStorage::onFieldStorageDefinition(Create|Update|Delete)() is broken for base fields.
parent fb4e8cdf
...@@ -189,8 +189,13 @@ protected function getChangeList() { ...@@ -189,8 +189,13 @@ protected function getChangeList() {
// Detect updated field storage definitions. // Detect updated field storage definitions.
foreach (array_intersect_key($storage_definitions, $original_storage_definitions) as $field_name => $storage_definition) { foreach (array_intersect_key($storage_definitions, $original_storage_definitions) as $field_name => $storage_definition) {
// @todo Support non-storage-schema-changing definition updates too: // @todo Support non-storage-schema-changing definition updates too:
// https://www.drupal.org/node/2336895. // https://www.drupal.org/node/2336895. So long as we're checking
if ($this->requiresFieldStorageSchemaChanges($storage_definition, $original_storage_definitions[$field_name])) { // based on schema change requirements rather than definition
// equality, skip the check if the entity type itself needs to be
// updated, since that can affect the schema of all fields, so we
// want to process that update first without reporting false
// positives here.
if (!isset($change_list[$entity_type_id]['entity_type']) && $this->requiresFieldStorageSchemaChanges($storage_definition, $original_storage_definitions[$field_name])) {
$field_changes[$field_name] = static::DEFINITION_UPDATED; $field_changes[$field_name] = static::DEFINITION_UPDATED;
} }
} }
......
...@@ -1165,7 +1165,7 @@ protected function deleteLastInstalledDefinition($entity_type_id) { ...@@ -1165,7 +1165,7 @@ protected function deleteLastInstalledDefinition($entity_type_id) {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getLastInstalledFieldStorageDefinitions($entity_type_id) { public function getLastInstalledFieldStorageDefinitions($entity_type_id) {
return $this->installedDefinitions->get($entity_type_id . '.field_storage_definitions'); return $this->installedDefinitions->get($entity_type_id . '.field_storage_definitions', array());
} }
/** /**
......
...@@ -67,4 +67,12 @@ public function requiresFieldStorageSchemaChanges(FieldStorageDefinitionInterfac ...@@ -67,4 +67,12 @@ public function requiresFieldStorageSchemaChanges(FieldStorageDefinitionInterfac
*/ */
public function requiresFieldDataMigration(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original); public function requiresFieldDataMigration(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original);
/**
* Performs final cleanup after all data of a field has been purged.
*
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition
* The field being purged.
*/
public function finalizePurge(FieldStorageDefinitionInterface $storage_definition);
} }
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
class DefaultTableMapping implements TableMappingInterface { class DefaultTableMapping implements TableMappingInterface {
/** /**
* A list of field storage definitions that are available for this mapping. * The field storage definitions of this mapping.
* *
* @var \Drupal\Core\Field\FieldStorageDefinitionInterface[] * @var \Drupal\Core\Field\FieldStorageDefinitionInterface[]
*/ */
...@@ -101,7 +101,16 @@ public function getAllColumns($table_name) { ...@@ -101,7 +101,16 @@ public function getAllColumns($table_name) {
$this->allColumns[$table_name] = array_merge($this->allColumns[$table_name], array_values($this->getColumnNames($field_name))); $this->allColumns[$table_name] = array_merge($this->allColumns[$table_name], array_values($this->getColumnNames($field_name)));
} }
$this->allColumns[$table_name] = array_merge($this->allColumns[$table_name], $this->getExtraColumns($table_name)); // There is just one field for each dedicated storage table, thus
// $field_name can only refer to it.
if (isset($field_name) && $this->requiresDedicatedTableStorage($this->fieldStorageDefinitions[$field_name])) {
// Unlike in shared storage tables, in dedicated ones field columns are
// positioned last.
$this->allColumns[$table_name] = array_merge($this->getExtraColumns($table_name), $this->allColumns[$table_name]);
}
else {
$this->allColumns[$table_name] = array_merge($this->allColumns[$table_name], $this->getExtraColumns($table_name));
}
} }
return $this->allColumns[$table_name]; return $this->allColumns[$table_name];
} }
...@@ -179,6 +188,47 @@ public function setExtraColumns($table_name, array $column_names) { ...@@ -179,6 +188,47 @@ public function setExtraColumns($table_name, array $column_names) {
return $this; return $this;
} }
/**
* Checks whether the given field can be stored in a shared table.
*
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition
* The field storage definition.
*
* @return bool
* TRUE if the field can be stored in a dedicated table, FALSE otherwise.
*/
public function allowsSharedTableStorage(FieldStorageDefinitionInterface $storage_definition) {
return !$storage_definition->hasCustomStorage() && $storage_definition->isBaseField() && !$storage_definition->isMultiple();
}
/**
* Checks whether the given field has to be stored in a dedicated table.
*
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition
* The field storage definition.
*
* @return bool
* TRUE if the field can be stored in a dedicated table, FALSE otherwise.
*/
public function requiresDedicatedTableStorage(FieldStorageDefinitionInterface $storage_definition) {
return !$storage_definition->hasCustomStorage() && !$this->allowsSharedTableStorage($storage_definition);
}
/**
* Returns a list of dedicated table names for this mapping.
*
* @return string[]
* An array of table names.
*/
public function getDedicatedTableNames() {
$table_mapping = $this;
$definitions = array_filter($this->fieldStorageDefinitions, function($definition) use ($table_mapping) { return $table_mapping->requiresDedicatedTableStorage($definition); });
$data_tables = array_map(function($definition) use ($table_mapping) { return $table_mapping->getDedicatedDataTableName($definition); }, $definitions);
$revision_tables = array_map(function($definition) use ($table_mapping) { return $table_mapping->getDedicatedRevisionTableName($definition); }, $definitions);
$dedicated_tables = array_merge(array_values($data_tables), array_values($revision_tables));
return $dedicated_tables;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
......
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException;
use Drupal\Core\Entity\Query\QueryInterface; use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Entity\Schema\FieldableEntityStorageSchemaInterface; use Drupal\Core\Entity\Schema\FieldableEntityStorageSchemaInterface;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageInterface;
use Drupal\field\FieldStorageConfigInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
...@@ -33,9 +33,8 @@ ...@@ -33,9 +33,8 @@
* *
* The class uses \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema * The class uses \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema
* internally in order to automatically generate the database schema based on * internally in order to automatically generate the database schema based on
* the defined base fields. Entity types can override * the defined base fields. Entity types can override the schema handler to
* SqlContentEntityStorage::getSchema() to customize the generated * customize the generated schema; e.g., to add additional indexes.
* schema; e.g., to add additional indexes.
* *
* @ingroup entity_api * @ingroup entity_api
*/ */
...@@ -107,11 +106,11 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt ...@@ -107,11 +106,11 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
protected $entityManager; protected $entityManager;
/** /**
* The entity schema handler. * The entity type's storage schema object.
* *
* @var \Drupal\Core\Entity\Schema\EntityStorageSchemaInterface * @var \Drupal\Core\Entity\Schema\EntityStorageSchemaInterface
*/ */
protected $schemaHandler; protected $storageSchema;
/** /**
* Cache backend. * Cache backend.
...@@ -157,15 +156,27 @@ public function getFieldStorageDefinitions() { ...@@ -157,15 +156,27 @@ public function getFieldStorageDefinitions() {
*/ */
public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache) { public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache) {
parent::__construct($entity_type); parent::__construct($entity_type);
$this->database = $database; $this->database = $database;
$this->entityManager = $entity_manager; $this->entityManager = $entity_manager;
$this->cacheBackend = $cache; $this->cacheBackend = $cache;
$this->initTableLayout();
}
/**
* Initializes table name variables.
*/
protected function initTableLayout() {
// Reset table field values to ensure changes in the entity type definition
// are correctly reflected in the table layout.
$this->tableMapping = NULL;
$this->revisionKey = NULL;
$this->revisionTable = NULL;
$this->dataTable = NULL;
$this->revisionDataTable = NULL;
// @todo Remove table names from the entity type definition in // @todo Remove table names from the entity type definition in
// https://drupal.org/node/2232465 // https://drupal.org/node/2232465
$this->baseTable = $this->entityType->getBaseTable() ?: $this->entityTypeId; $this->baseTable = $this->entityType->getBaseTable() ?: $this->entityTypeId;
$revisionable = $this->entityType->isRevisionable(); $revisionable = $this->entityType->isRevisionable();
if ($revisionable) { if ($revisionable) {
$this->revisionKey = $this->entityType->getKey('revision') ?: 'revision_id'; $this->revisionKey = $this->entityType->getKey('revision') ?: 'revision_id';
...@@ -223,32 +234,57 @@ public function getRevisionDataTable() { ...@@ -223,32 +234,57 @@ public function getRevisionDataTable() {
} }
/** /**
* Gets the schema handler for this entity storage. * Returns the entity type's storage schema object.
* *
* @return \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema * @return \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema
* The schema handler. * The schema object.
*/ */
protected function schemaHandler() { protected function getStorageSchema() {
if (!isset($this->schemaHandler)) { if (!isset($this->storageSchema)) {
$schema_handler_class = $this->entityType->getHandlerClass('storage_schema') ?: 'Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema'; $class = $this->entityType->getHandlerClass('storage_schema') ?: 'Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema';
$this->schemaHandler = new $schema_handler_class($this->entityManager, $this->entityType, $this, $this->database); $this->storageSchema = new $class($this->entityManager, $this->entityType, $this, $this->database);
} }
return $this->schemaHandler; return $this->storageSchema;
} }
/** /**
* {@inheritdoc} * Updates the wrapped entity type definition.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The update entity type.
*
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* See https://www.drupal.org/node/2274017.
*/ */
public function getTableMapping() { public function setEntityType(EntityTypeInterface $entity_type) {
if (!isset($this->tableMapping)) { if ($this->entityType->id() == $entity_type->id()) {
$this->entityType = $entity_type;
$this->initTableLayout();
}
else {
throw new EntityStorageException(String::format('Unsupported entity type @id', array('@id' => $entity_type->id())));
}
}
$definitions = array_filter($this->getFieldStorageDefinitions(), function (FieldStorageDefinitionInterface $definition) { /**
// @todo Remove the check for FieldDefinitionInterface::isMultiple() when * {@inheritdoc}
// multiple-value base fields are supported in */
// https://drupal.org/node/2248977. public function getTableMapping(array $storage_definitions = NULL) {
return !$definition->hasCustomStorage() && !$definition->isMultiple(); $table_mapping = $this->tableMapping;
// If we are using our internal storage definitions, which is our main use
// case, we can statically cache the computed table mapping. If a new set
// of field storage definitions is passed, for instance when comparing old
// and new storage schema, we compute the table mapping without caching.
// @todo Clean-up this in https://www.drupal.org/node/2274017 so we can
// easily instantiate a new table mapping whenever needed.
if (!isset($this->tableMapping) || $storage_definitions) {
$definitions = $storage_definitions ?: $this->entityManager->getFieldStorageDefinitions($this->entityTypeId);
$table_mapping = new DefaultTableMapping($definitions);
$definitions = array_filter($definitions, function (FieldStorageDefinitionInterface $definition) use ($table_mapping) {
return $table_mapping->allowsSharedTableStorage($definition);
}); });
$this->tableMapping = new DefaultTableMapping($definitions);
$key_fields = array_values(array_filter(array($this->idKey, $this->revisionKey, $this->bundleKey, $this->uuidKey, $this->langcodeKey))); $key_fields = array_values(array_filter(array($this->idKey, $this->revisionKey, $this->bundleKey, $this->uuidKey, $this->langcodeKey)));
$all_fields = array_keys($definitions); $all_fields = array_keys($definitions);
...@@ -272,16 +308,16 @@ public function getTableMapping() { ...@@ -272,16 +308,16 @@ public function getTableMapping() {
$translatable = $this->entityType->isTranslatable(); $translatable = $this->entityType->isTranslatable();
if (!$revisionable && !$translatable) { if (!$revisionable && !$translatable) {
// The base layout stores all the base field values in the base table. // The base layout stores all the base field values in the base table.
$this->tableMapping->setFieldNames($this->baseTable, $all_fields); $table_mapping->setFieldNames($this->baseTable, $all_fields);
} }
elseif ($revisionable && !$translatable) { elseif ($revisionable && !$translatable) {
// The revisionable layout stores all the base field values in the base // The revisionable layout stores all the base field values in the base
// table, except for revision metadata fields. Revisionable fields // table, except for revision metadata fields. Revisionable fields
// denormalized in the base table but also stored in the revision table // denormalized in the base table but also stored in the revision table
// together with the entity ID and the revision ID as identifiers. // together with the entity ID and the revision ID as identifiers.
$this->tableMapping->setFieldNames($this->baseTable, array_diff($all_fields, $revision_metadata_fields)); $table_mapping->setFieldNames($this->baseTable, array_diff($all_fields, $revision_metadata_fields));
$revision_key_fields = array($this->idKey, $this->revisionKey); $revision_key_fields = array($this->idKey, $this->revisionKey);
$this->tableMapping->setFieldNames($this->revisionTable, array_merge($revision_key_fields, $revisionable_fields)); $table_mapping->setFieldNames($this->revisionTable, array_merge($revision_key_fields, $revisionable_fields));
} }
elseif (!$revisionable && $translatable) { elseif (!$revisionable && $translatable) {
// Multilingual layouts store key field values in the base table. The // Multilingual layouts store key field values in the base table. The
...@@ -290,7 +326,7 @@ public function getTableMapping() { ...@@ -290,7 +326,7 @@ public function getTableMapping() {
// denormalized copy of the bundle field value to allow for more // denormalized copy of the bundle field value to allow for more
// performant queries. This means that only the UUID is not stored on // performant queries. This means that only the UUID is not stored on
// the data table. // the data table.
$this->tableMapping $table_mapping
->setFieldNames($this->baseTable, $key_fields) ->setFieldNames($this->baseTable, $key_fields)
->setFieldNames($this->dataTable, array_values(array_diff($all_fields, array($this->uuidKey)))) ->setFieldNames($this->dataTable, array_values(array_diff($all_fields, array($this->uuidKey))))
// Add the denormalized 'default_langcode' field to the mapping. Its // Add the denormalized 'default_langcode' field to the mapping. Its
...@@ -306,13 +342,13 @@ public function getTableMapping() { ...@@ -306,13 +342,13 @@ public function getTableMapping() {
// holds the data field values for all non-revisionable fields. The data // holds the data field values for all non-revisionable fields. The data
// field values of revisionable fields are denormalized in the data // field values of revisionable fields are denormalized in the data
// table, as well. // table, as well.
$this->tableMapping->setFieldNames($this->baseTable, array_values(array_diff($key_fields, array($this->langcodeKey)))); $table_mapping->setFieldNames($this->baseTable, array_values(array_diff($key_fields, array($this->langcodeKey))));
// Like in the multilingual, non-revisionable case the UUID is not // Like in the multilingual, non-revisionable case the UUID is not
// in the data table. Additionally, do not store revision metadata // in the data table. Additionally, do not store revision metadata
// fields in the data table. // fields in the data table.
$data_fields = array_values(array_diff($all_fields, array($this->uuidKey), $revision_metadata_fields)); $data_fields = array_values(array_diff($all_fields, array($this->uuidKey), $revision_metadata_fields));
$this->tableMapping $table_mapping
->setFieldNames($this->dataTable, $data_fields) ->setFieldNames($this->dataTable, $data_fields)
// Add the denormalized 'default_langcode' field to the mapping. Its // Add the denormalized 'default_langcode' field to the mapping. Its
// value is identical to the query expression // value is identical to the query expression
...@@ -321,20 +357,45 @@ public function getTableMapping() { ...@@ -321,20 +357,45 @@ public function getTableMapping() {
->setExtraColumns($this->dataTable, array('default_langcode')); ->setExtraColumns($this->dataTable, array('default_langcode'));
$revision_base_fields = array_merge(array($this->idKey, $this->revisionKey, $this->langcodeKey), $revision_metadata_fields); $revision_base_fields = array_merge(array($this->idKey, $this->revisionKey, $this->langcodeKey), $revision_metadata_fields);
$this->tableMapping->setFieldNames($this->revisionTable, $revision_base_fields); $table_mapping->setFieldNames($this->revisionTable, $revision_base_fields);
$revision_data_key_fields = array($this->idKey, $this->revisionKey, $this->langcodeKey); $revision_data_key_fields = array($this->idKey, $this->revisionKey, $this->langcodeKey);
$revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields); $revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields, array($this->langcodeKey));
$this->tableMapping $table_mapping
->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields)) ->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields))
// Add the denormalized 'default_langcode' field to the mapping. Its // Add the denormalized 'default_langcode' field to the mapping. Its
// value is identical to the query expression // value is identical to the query expression
// "revision_table.langcode = data_table.langcode". // "revision_table.langcode = data_table.langcode".
->setExtraColumns($this->revisionDataTable, array('default_langcode')); ->setExtraColumns($this->revisionDataTable, array('default_langcode'));
} }
// Add dedicated tables.
$definitions = array_filter($definitions, function (FieldStorageDefinitionInterface $definition) use ($table_mapping) {
return $table_mapping->requiresDedicatedTableStorage($definition);
});
$extra_columns = array(
'bundle',
'deleted',
'entity_id',
'revision_id',
'langcode',
'delta',
);
foreach ($definitions as $field_name => $definition) {
foreach (array($table_mapping->getDedicatedDataTableName($definition), $table_mapping->getDedicatedRevisionTableName($definition)) as $table_name) {
$table_mapping->setFieldNames($table_name, array($field_name));
$table_mapping->setExtraColumns($table_name, $extra_columns);
}
}
// Cache the computed table mapping only if we are using our internal
// storage definitions.
if (!$storage_definitions) {
$this->tableMapping = $table_mapping;
}
} }
return $this->tableMapping; return $table_mapping;
} }
/** /**
...@@ -581,7 +642,7 @@ protected function attachPropertyData(array &$entities) { ...@@ -581,7 +642,7 @@ protected function attachPropertyData(array &$entities) {
$table_mapping = $this->getTableMapping(); $table_mapping = $this->getTableMapping();
$translations = array(); $translations = array();
if ($this->revisionDataTable) { if ($this->revisionDataTable) {
$data_fields = array_diff_key($table_mapping->getFieldNames($this->revisionDataTable), $table_mapping->getFieldNames($this->baseTable)); $data_fields = array_diff($table_mapping->getFieldNames($this->revisionDataTable), $table_mapping->getFieldNames($this->baseTable));
} }
else { else {
$data_fields = $table_mapping->getFieldNames($this->dataTable); $data_fields = $table_mapping->getFieldNames($this->dataTable);
...@@ -1150,7 +1211,7 @@ protected function loadFieldItems(array $entities) { ...@@ -1150,7 +1211,7 @@ protected function loadFieldItems(array $entities) {
$definitions[$bundle] = $this->entityManager->getFieldDefinitions($this->entityTypeId, $bundle); $definitions[$bundle] = $this->entityManager->getFieldDefinitions($this->entityTypeId, $bundle);
foreach ($definitions[$bundle] as $field_name => $field_definition) { foreach ($definitions[$bundle] as $field_name => $field_definition) {
$storage_definition = $field_definition->getFieldStorageDefinition(); $storage_definition = $field_definition->getFieldStorageDefinition();
if ($this->usesDedicatedTable($storage_definition)) { if ($table_mapping->requiresDedicatedTableStorage($storage_definition)) {
$storage_definitions[$field_name] = $storage_definition; $storage_definitions[$field_name] = $storage_definition;
} }
} }
...@@ -1225,7 +1286,7 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) { ...@@ -1225,7 +1286,7 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) {
foreach ($this->entityManager->getFieldDefinitions($entity_type, $bundle) as $field_name => $field_definition) { foreach ($this->entityManager->getFieldDefinitions($entity_type, $bundle) as $field_name => $field_definition) {
$storage_definition = $field_definition->getFieldStorageDefinition(); $storage_definition = $field_definition->getFieldStorageDefinition();
if (!$this->usesDedicatedTable($storage_definition)) { if (!$table_mapping->requiresDedicatedTableStorage($storage_definition)) {
continue; continue;
} }
$table_name = $table_mapping->getDedicatedDataTableName($storage_definition); $table_name = $table_mapping->getDedicatedDataTableName($storage_definition);
...@@ -1240,10 +1301,12 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) { ...@@ -1240,10 +1301,12 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) {
->condition('entity_id', $id) ->condition('entity_id', $id)
->execute(); ->execute();
} }
$this->database->delete($revision_name) if ($this->entityType->isRevisionable()) {
->condition('entity_id', $id) $this->database->delete($revision_name)
->condition('revision_id', $vid) ->condition('entity_id', $id)
->execute(); ->condition('revision_id', $vid)
->execute();
}
} }
// Prepare the multi-insert query. // Prepare the multi-insert query.
...@@ -1253,7 +1316,9 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) { ...@@ -1253,7 +1316,9 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) {
$columns[] = $table_mapping->getFieldColumnName($storage_definition, $column); $columns[] = $table_mapping->getFieldColumnName($storage_definition, $column);
} }
$query = $this->database->insert($table_name)->fields($columns); $query = $this->database->insert($table_name)->fields($columns);
$revision_query = $this->database->insert($revision_name)->fields($columns); if ($this->entityType->isRevisionable()) {
$revision_query = $this->database->insert($revision_name)->fields($columns);
}
$langcodes = $field_definition->isTranslatable() ? $translation_langcodes : array($default_langcode); $langcodes = $field_definition->isTranslatable() ? $translation_langcodes : array($default_langcode);
foreach ($langcodes as $langcode) { foreach ($langcodes as $langcode) {
...@@ -1276,7 +1341,9 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) { ...@@ -1276,7 +1341,9 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) {
$record[$column_name] = !empty($attributes['serialize']) ? serialize($item->$column) : $item->$column; $record[$column_name] = !empty($attributes['serialize']) ? serialize($item->$column) : $item->$column;
} }
$query->values($record); $query->values($record);
$revision_query->values($record); if ($this->entityType->isRevisionable()) {
$revision_query->values($record);
}
if ($storage_definition->getCardinality() != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && ++$delta_count == $storage_definition->getCardinality()) { if ($storage_definition->getCardinality() != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && ++$delta_count == $storage_definition->getCardinality()) {
break; break;
...@@ -1291,7 +1358,9 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) { ...@@ -1291,7 +1358,9 @@ protected function saveFieldItems(EntityInterface $entity, $update = TRUE) {
if ($entity->isDefaultRevision()) { if ($entity->isDefaultRevision()) {
$query->execute(); $query->execute();
} }
$revision_query->execute(); if ($this->entityType->isRevisionable()) {
$revision_query->execute();
}
} }
} }
} }
...@@ -1306,7 +1375,7 @@ protected function deleteFieldItems(EntityInterface $entity) { ...@@ -1306,7 +1375,7 @@ protected function deleteFieldItems(EntityInterface $entity) {
$table_mapping = $this->getTableMapping(); $table_mapping = $this->getTableMapping();
foreach ($this->entityManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()) as $field_definition) { foreach ($this->entityManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()) as $field_definition) {
$storage_definition = $field_definition->getFieldStorageDefinition(); $storage_definition = $field_definition->getFieldStorageDefinition();
if (!$this->usesDedicatedTable($storage_definition)) { if (!$table_mapping->requiresDedicatedTableStorage($storage_definition)) {
continue; continue;
} }