Problem/Motivation

SqlContentEntityStorage::doSaveFieldItems() now assumes that entity id can be accessed via $entity->get($this->idKey)->value when updating entities. However this is not always the case.

Relevant diff from #2342699: SqlContentEntityStorage tries to update identity/serial values by default:

diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 150a18d64b..7edc4f6307 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -824,10 +824,13 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names
       if ($update) {
         $default_revision = $entity->isDefaultRevision();
         if ($default_revision) {
+          // Remove the ID from the record to enable updates on SQL variants
+          // that prevent updating serial columns, for example, mssql.
+          unset($record->{$this->idKey});
           $this->database
             ->update($this->baseTable)
             ->fields((array) $record)
-            ->condition($this->idKey, $record->{$this->idKey})
+            ->condition($this->idKey, $entity->get($this->idKey)->value)
             ->execute();
         }

Proposed resolution

Remaining tasks

User interface changes

API changes

CommentFileSizeAuthor
#2 3027574-2.patch1.03 KBtuutti

Comments

tuutti created an issue. See original summary.

tuutti’s picture

StatusFileSize
new1.03 KB
tstoeckler’s picture

However this is not always the case.

Can you explain how this can happen?

This patch doesn't really hurt, in fact I like the new code slightly better because it doesn't rely on $entity for that part. But would be interested to hear what @amateescu or someone else thinks.

tuutti’s picture

One example would be https://gist.github.com/tuutti/70160e09ad70659a7a19904c8f87f2b9 where we use entity_reference field as entity id (where the main property is target_id), but in theory this should break with any field that uses something else than value as the main property.

amateescu’s picture

Status: Active » Reviewed & tested by the community

I was about to write that a custom entity type might not use a field type with a value column/main property for its ID, but @tuutti beat me to it :)

Since that is completely supported by Entity API, I think the patch in #2 looks great :)

berdir’s picture

+1 on the fix, makes sense. entity_reference ID field is pretty crazy, but if you have a 1:1 relationship between entities, I guess that works ;)

This might get pushed back due to missing test coverage, for that we would need to add another test entity type like that example, the amount of test entity types that we already have makes me pretty sad ;)

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

As this is a regression I've committed this with no test. I do think it is worth having a follow-up to add this test case (an id field where value is not the main property) to core.

Committed and pushed 819a788ebd to 8.7.x and 2ecc2ee700 to 8.6.x. Thanks!

  • alexpott committed 819a788 on 8.7.x
    Issue #3027574 by tuutti: SqlContentEntityStorage no longer update...
alexpott’s picture

Issue tags: +Needs followup

  • alexpott committed 2ecc2ee on 8.6.x
    Issue #3027574 by tuutti: SqlContentEntityStorage no longer update...

Status: Fixed » Closed (fixed)

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