Problem/Motivation
Updating to 8.0.x-dev this morning I ran into a database update failure from system module.
Cannot change the definition of field comment.langcode: field doesn't exist. Failed: Cannot change the definition of field comment.langcode: field doesn't exist.
This is multisite installation. Strangely it occurred on only one of the sites. As you can see below I do not have comment module enabled (nor is it enabled on any of the other sites in the installation).
I didn't capture the original failure, which occurred alongside several other successful updates. But this is the output from when I re-ran it:
$ drush updb The following updates are pending: system module : 8007 - Set langcode fields to be ASCII-only. Do you wish to run all pending updates? (y/n): y Cannot change the definition of field comment.langcode: field doesn't exist. [error] Performing system_update_8007 [ok] Failed: Cannot change the definition of field comment.langcode: field doesn't exist. [error] Cache rebuild complete. [ok] Finished performing updates. [ok] $ drush pm-list --status=enabled --type=module Package Name Version Core Block (block) 8.0.0-dev Core Breakpoint (breakpoint) 8.0.0-dev Core CKEditor (ckeditor) 8.0.0-dev Core Color (color) 8.0.0-dev Core Configuration Manager (config) 8.0.0-dev Core Contextual Links (contextual) 8.0.0-dev Core Custom Block (block_content) 8.0.0-dev Core Custom Menu Links (menu_link_content) 8.0.0-dev Core Database Logging (dblog) 8.0.0-dev Core Field (field) 8.0.0-dev Core Field UI (field_ui) 8.0.0-dev Core Filter (filter) 8.0.0-dev Core Help (help) 8.0.0-dev Core History (history) 8.0.0-dev Core Internal Page Cache (page_cache) 8.0.0-dev Core Menu UI (menu_ui) 8.0.0-dev Core Node (node) 8.0.0-dev Core Path (path) 8.0.0-dev Core Quick Edit (quickedit) 8.0.0-dev Core RDF (rdf) 8.0.0-dev Core Search (search) 8.0.0-dev Core Shortcut (shortcut) 8.0.0-dev Core System (system) 8.0.0-dev Core Taxonomy (taxonomy) 8.0.0-dev Core Text Editor (editor) 8.0.0-dev Core Toolbar (toolbar) 8.0.0-dev Core Tour (tour) 8.0.0-dev Core Update Manager (update) 8.0.0-dev Core User (user) 8.0.0-dev Core Views (views) 8.0.0-dev Core Views UI (views_ui) 8.0.0-dev Development Devel (devel) 8.x-1.x-dev Field types Datetime (datetime) 8.0.0-dev Field types Entity Reference (entity_reference) 8.0.0-dev Field types File (file) 8.0.0-dev Field types Image (image) 8.0.0-dev Field types Link (link) 8.0.0-dev Field types Options (options) 8.0.0-dev Field types Text (text) 8.0.0-dev $ drush pmi system --fields=schema_version Schema version : 8006
I bypassed the failure by manually updating the module schema version.
Proposed resolution
* Add an update path to truncate unneeded entry from the key value (system_update_8008
)
* Ensure in system_update_8007
that it skips entity types which aren't in there
* Write an update path
Comments
Comment #2
dawehnerYou can certainly reproduce that by install beta 13, uninstall comment and update to HEAD/beta15
The underlying problem is that uninstalls doesn't cleanup those state entries ...
Comment #3
stefan.r CreditAttribution: stefan.r commentedThis sounds major and possibly critical
Comment #4
catchIf I'm reading #2 correctly it sounds like uninstalling an entity-providing module leaves the entity/field definitions in state - so the system thinks there are tables there which are not?
Bumping to critical for now since this leaves sites in an unrecoverable state and uninstalling a module then updating a core version is fairly basic.
If this is not a generic problem and only something wrong with the beta13-15 update path then it could go back to major though.
Comment #5
k4v CreditAttribution: k4v as a volunteer commentedComment #6
dawehnerExactly
Comment #7
k4v CreditAttribution: k4v as a volunteer commentedComment #8
k4v CreditAttribution: k4v as a volunteer commentedFirst the test, that should come out red.
Comment #9
k4v CreditAttribution: k4v as a volunteer commentedThis could be green..... please.
Comment #10
BerdirComment #11
k4v CreditAttribution: k4v as a volunteer commentedComment #12
BerdirWe don't need to implement a hook for this, just put the logic in ModuleInstaller::uninstall().
Comment #13
k4v CreditAttribution: k4v as a volunteer commentedok, moved it.
Comment #16
dawehnerDo we need to take care of
entity.definitions.installed
as well?It feels like a better name for
$item
would be nice!We should name it
$entity_type_id
Nitpick: code style
In an ideal world:
\Drupal\system\Tests\Entity\EntitySchemaTest
would be extended.In an ideal world we would also have an update path test.
Comment #17
YesCT CreditAttribution: YesCT commentedI think we can more simply word the comment.
Delete entities from the storage schema if they are from modules that are not installed.
Hm...
We are getting all the entity definitions, and then deleting items from the store if they are not in that list.
More general than only the case of a module being uninstalled. Oh, but maybe this is in uninstall code... Yep. helps to apply the patch and look at it in context. ;)
Actually, I read this a few more times, and leaving the comment as is is probably fine.
why is this string split into two strings and concatenated?
maybe to fit on 80 char line? it can just be all one line.
On thinking some more, the string probably would be better as a comment before the assert. "After uninstalling, ensure there are no comment entity fields in the schema." Then, just let the assert give the default message.
Comment #18
YesCT CreditAttribution: YesCT commentedThe fail in #8 was nice, just what was expected for the tests only patch.
The fail was:
Interesting, that we got both the custom message and the default X is equal to Y.
(not we should still not concatenate the message though)
Comment #19
k4v CreditAttribution: k4v as a volunteer commentedAfter talking to @dawehner, I try to move the test code to EntiySchemaTest
Comment #20
xjm@YesCT this long-awaited feature for assertions is from #2571291: In WebTest code, assertEqual and assertIdentical should always show the 2 values on failure. :)
Comment #23
k4v CreditAttribution: k4v as a volunteer commentedWe moved the test code to EntitySchemaTest.
After feedback from yched and plach we will try to move the fix to SqlContentEntityStorageSchema->onEntityTypeDelete().
Comment #24
dawehnerNice!
Now we just need to merge everything together properly
Comment #25
YesCT CreditAttribution: YesCT commentedk4v and I are working together.
we figured out how to run the test on the command line! yay
php scripts/run-tests.sh --sqlite /tmp/db2.sqlite --dburl sqlite://localhost//tmp/db2.sqlite --class "\Drupal\system\Tests\Entity\EntitySchemaTest::testCleanUpStorageDefinition"
https://www.drupal.org/node/645286 helped us figure that out (with help from Sutharsan and @dawehner)
--
great. I'm going to do a few clean ups on the test.
let's let the testbot run on it in the mean time. setting to needs review.
Comment #26
k4v CreditAttribution: k4v as a volunteer commentedoops, forgot the interdiff.
Comment #27
YesCT CreditAttribution: YesCT commentedsome standards and comment improvements on the test.
feedback on the test welcome. :) we are moving onto working on the fix.
Comment #30
k4v CreditAttribution: k4v as a volunteer commentedThis fixes a typo in the last patches.
Comment #31
dawehnerWhat about recording all the entity types above and check all of them after the uninstall?
Comment #33
k4v CreditAttribution: k4v as a volunteer commentedSo finally we moved the fix to SqlContentEntityStorageSchema->onEntityTypeDelete().
Comment #34
YesCT CreditAttribution: YesCT commentedoh... regarding #31
I think I see. The concern is that the entity_test module is providing storage definitions that start with entity_test. and also other patterns.
and then we are only checking that the ones that match exactly the modulename. are being deleted.
we need to find a list of the ones entity_test provides and then make sure all of those were deleted.
Comment #36
k4v CreditAttribution: k4v as a volunteer commentedWe think we addressed all the concerns.
Before we we only deleting storage definitions that began with the module name. Now we delete storage definitions that begin with entity type ids that are provided by the module.
Also we count the right stuff in the test now and corrected the assertion message.
¡¡¡¡¡¡¡¡¡¡¡YAY!!!!!!!!!!
As far as we know we're done and are looking forward for thorough reviews.
Comment #37
dawehnerOverall this looks kinda clean, just some non optional variable names.
Some space after the if would be nice
We could rename $name to $entity_type_id and things would be just way clearer.
If we rename
$entity_item
to$entity_type_id
The message should be written for the case in which its properly working
Let's rename
$item_count
to$containing_entity_type_ids
Comment #42
jhedstromThis looks great.
One possible suggestion to add while incorporating the feedback above:
For completeness sake (even though I'm sure this is tested elsewhere), I think it would be good to ensure these storage schemas are present prior to disabling the module, so we're absolutely sure of this test. A simple count while installing schemas, then an assertion of that count should suffice.
Comment #43
YesCT CreditAttribution: YesCT commented@dawehner Thank you for reviewing this again. Sorry about 1. You mentioned it before, and I thought I checked it was done... it *is* now!
ok. I am on it.
Comment #44
YesCT CreditAttribution: YesCT commentedjust addressing #37
I will do #42 next.
Comment #45
YesCT CreditAttribution: YesCT commented@jhedstrom thank you for reviewing this.
addressing #42. makes sure there are some storage definitions provided by the entity_test module, before we try and make sure there are none after uninstalling the module.
back to needing comprehensive review.
Comment #46
dawehnerlist($entity_type_id, ) = explode('.', $storage_definition_name, 2);
would be a bit easier to read?Comment #47
k4v CreditAttribution: k4v as a volunteer commentedFlight is delayed, I'm @airport
One thing that just came to my mind: This patch does not fix the original problem upgrading from Beta 13 to HEAD. Should there be code to work around this bug to make upgraders happy?
Comment #48
k4v CreditAttribution: k4v as a volunteer commentedI think about putting the cleanup routine in the update hook. Feedback?
Comment #49
plachWorking on a small improvement
Comment #50
plach@k4v:
Yes, feel free to write a db update function. It will need to detect all data that's not belonging to an installed entity type returned by the entity manager. We'll need also a db update test to check that this works properly.
Comment #51
plachThis should be slightly cleaner
Comment #52
plach@k4v:
Please file a follow-up for the update stuff, I discussed this with @dawehner and @YesCT and we agreed that part is not critical. We should be done here now, thanks!
Comment #53
dawehner@k4v
We discussed this here again. We need an update path, as otherwise things are broken.
Comment #54
dawehner@k4v
When do you have boarding? We can work on the update here pretty easy.
Comment #55
plachI'll work on the test.
Comment #56
YesCT CreditAttribution: YesCT commentedchange in #51 makes a lot of sense. thanks @plach
Comment #57
stefan.r CreditAttribution: stefan.r commentedPatch looks great! Just for completeness can we post a test-only patch?
"have...having" sounds a bit odd, maybe just "have...with"?
Comment #58
plachHere's the test for the upcoming test function, this is now expected to fail.
Comment #61
plachAnd here is the update function, improved also test coverage.
Comment #62
plachComment #63
dawehnerBeside this I think this is ready to go.
I'd use
explode(, , 2)
Let's use the
explode(, , 2)
all over the place.Comment #64
YesCT CreditAttribution: YesCT commentedI will work on that now.
Comment #65
YesCT CreditAttribution: YesCT commentedsince I just want the first thing, I dont need the ,2.
Comment #66
dawehnerThank you YescCT, RTBC conce its green
Comment #67
dawehnerIts green now, thank you
Comment #68
Wim LeersSilly things that can be fixed on commit:
Nit: "have … having" is strange.
s/entities/entity types/
I could be wrong.
Comment #69
alexpottNice work everyone. Committed 3287afb and pushed to 8.0.x. Thanks!
Comment #70
alexpottI didn't address #68 - can be cleanup in a followup.