Problem/Motivation
When translations are enabled for content with data, and index is added to the content_translation_uid field. However, the stored entity schema for that type is not updated, triggering a need to run automatic entity updates. When those are run however, since the index already exists, this uncaught exception is thrown:
Cannot add index taxonomy_term__1a0c187e9a to table taxonomy_term_field_data: index already exists
The only recent issue I could find that may have caused this is #2472621: Translatable entity 'created' and 'uid' fields not initialized properly during content translation 'Add'.
Steps to reproduce
- Add some term data
- Enable the
content_translationmodule - Enable translations on taxonomy terms at
admin/config/regional/content-language - Attempt to run updates
- See the exception
Proposed resolution
Make SqlContentEntityStorageSchema consistent in checking for pre-existing indexes before trying to create them. Add test coverage. We have additional implicit test coverage through #2555183: Fix the filled update tests, they are broken too.
Remaining tasks
n/a
User interface changes
n/a
API changes
n/a
Data model changes
n/a
| Comment | File | Size | Author |
|---|---|---|---|
| #28 | content-translation-uid-index-2555665-28.patch | 5.33 KB | jhedstrom |
Comments
Comment #2
jhedstromComment #3
jhedstromElsewhere in
SqlContentEntityStorageSchemathere are already checks for pre-existing indexes, so this approach just makes that consistent. With this patch, the number of exceptions thrown in #2555183-12: Fix the filled update tests, they are broken is greatly reduced.Comment #4
stefan.r commentedThis looks like a reasonable way to fix this, would a new addIndexIfNotExists() method make sense here? Or alternatively is there an easy way to persist whether the index has been updated during the earlier entity type update event?
Comment #5
jhedstromThis adds the new method to simplify the code a bit.
Before the approach in #3, I tried to determine where/when the index was added (it is at some point after translation is enabled for a given entity type, via the
ContentTranslationUpdatesManager), but I couldn't pinpoint exactly when the index was added.Comment #6
stefan.r commentedLooks good!
Comment #7
stefan.r commentedJust to add to that, this issue fixes a bug in our upgrade path and is blocking a critical: #2555183: Fix the filled update tests, they are broken
Comment #8
stefan.r commentedComment #9
catchGiving plach a chance to take a look.
Comment #10
plachIt's a bit late here and I'd like to have a look to this with a fresh mind, but I'm not seeing additional test coverage: is this assuming implicit test coverage is provided by #2555183: Fix the filled update tests, they are broken?
Comment #11
jhedstromThis patch resolved some 150+ fails in #2555183: Fix the filled update tests, they are broken, so perhaps the implicit coverage is enough?
Comment #12
jhedstromSorry, I misspoke above. This patch only resolved a handful of fails, the vast majority were schema mismatches addressed by other patches.
Comment #13
gábor hojtsyElevating to critical because #2555183: Fix the filled update tests, they are broken is a critical and is dependent on this being fixed.
Comment #16
stefan.r commentedComment #17
stefan.r commentedComment #18
stefan.r commentedIt's the parent that needed an IS update, not this one...
Comment #19
plachCan you please explain the following sentence?
That field is defined by the Content Translation module, so when translations are enabled for a certain bundle already having data, the field should either exist or not exist. If I'm looking at the code right, it seems the
ContentTranslationUpdatesManageronly triggers updates for newly added fields, so what's the scenario where only an index is added?I assume the
updateop is applied to thecontent_translation_uidfield, but it's not clear to me how that can happen. Anyway, if that's the case, how can be sure the old index specification perfectly matches the current one? Shouldn't we drop the index and re-create it as we do in the other cases?Comment #20
xjmComment #21
gábor hojtsyAt least a quick reroll for now.
Comment #22
gábor hojtsySo looks like this does not have tests on its own to prove when is the problem happening. BUT https://qa.drupal.org/pifr/test/1133538 exposes the issue with just running the filled database dump through updates. Fails on
Index users__id__default_langcode__langcode properly created on the user_field_data table in SqlContentEntityStorageSchemaIndexTest.php:44Among other things.
Comment #23
penyaskitoWhat happens if the fields indexed have changed? As @plach mentioned in #19, we need to alter the index instead.
Comment #24
stefan.r commentedComment #25
stefan.r commentedComment #26
jhedstromI'll work on checking for index changes. I think we'll have to drop and re-create indexes if a change is detected.
Comment #27
plachAgreed
Comment #28
jhedstromAfter digging into this, we're already dropping existing indexes before updating them. From
SqlContentEntityStorageSchema::updateSharedTableSchema():and from
SqlContentEntityStorageSchema::onEntityTypeUpdate():I've added a test to illustrate this.
The reason this is an issue is that there is no record of the previous index (if there were, it would be dropped), so I still think the fix is reasonable to check if a newly added index has been added by another process (in this case the
ContentTranslationUpdatesManager.Comment #29
xjmDiscussed with @webchick, @effulgentsia, @alexpott, and @catch. This issue is critical as a blocker for #2555183: Fix the filled update tests, they are broken and also independently a bug with entity update functionality.
Comment #30
effulgentsia commentedTagging beta target per #2341575-45: [meta] Provide a beta to beta/rc upgrade path.
Comment #31
gábor hojtsy@jhedstrom: that makes sense. Thanks for the explicit test coverage, looks good to me. More implicit test coverage will be added in #2555183: Fix the filled update tests, they are broken.
Comment #32
gábor hojtsyComment #33
plachLooks ready to go.
I will have a another look to this anyway, but don't block commit on my further feedback.
Comment #34
webchickEssentially, this is just adding a new method—addIndexIfNotExists()—and calling it in place of addIndex() to get around the problem. Looks straight-forward to me, and unblocks a blocker of a blocker. ;)
Committed and pushed to 8.0.x. Thanks!
Comment #36
plach@webchick:
I still don't get why the original problem manifests, but that's just the "Content Translation maintainer" inside me speaking.
The "release Drupal 8 for the love of God" guy inside me just says "yay, one sucker less!" ;)
Comment #37
catchFix here wasn't correct after all, see #2561129: Composite indexes are not correctly deleted/re-created when updating a field storage definition.
Comment #38
gábor hojtsy