Problem/Motivation
The following test failure is occurring on postgres. This is a newly added test, so it's likely a driver issue rather than a regression.
https://www.drupal.org/pift-ci-job/25521
fail: [Other] Line 43 of core/modules/system/src/Tests/Entity/Update/SqlContentEntityStorageSchemaIndexTest.php:
Index node__id__default_langcode__langcode properly created on the node_field_data table.
Tagging beta target because it would be good to confirm it really is a postgres driver issue and not a hidden upgrade path bug.
Proposed resolution
Drop and re-create composite indexes whenever a field involving them is dropped or created.
Remaining tasks
Validate the proposed solutionCode it- Reviews
User interface changes
None
API changes
None
Data model changes
None
Comment | File | Size | Author |
---|---|---|---|
#30 | entity-schema_composite_indexes-2561129-30.patch | 18.22 KB | plach |
#22 | entity-schema_composite_indexes-2561129-22.test.patch | 4.06 KB | plach |
Comments
Comment #2
catchComment #3
alexpottWhat's awesome is that Drupal\system\Tests\Entity\Update\SqlContentEntityStorageSchemaIndexFilledTest passes... so this is a difference between what occurs when the db is empty and when it is has data.
Comment #4
catchComment #5
alexpottIn node_update_8002()...
So the index is created correctly during the first update but then deleted in the next one... weird and scary this is different between SQL engines.
Comment #6
effulgentsia CreditAttribution: effulgentsia at Acquia commentedThose are different indexes. We're dropping 2 old indexes and creating one new one with more fields. The error message in the issue summary indicates that it is the index creation that is broken (in the presence of existing data). I don't have experience with Postgres to know if that's a common problem.
Comment #7
effulgentsia CreditAttribution: effulgentsia at Acquia commentedOh, unless you're saying that the new index,
node__id__default_langcode__langcode
, is being attempted to get created twice: once for each line of code in #5, and MySQL is more forgiving of that than Postgres? I haven't debugged to see if any of this true, just speculating based on what's written in #5.Comment #8
alexpottSo the problem occurs because when
$manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('langcode', 'node'));
fires on an empty db it ends up dropping and recreating the langcode column. In postgres land this causes the index added on the entity level to be dropped because the column is part of the index. In mysql land this doesn't happen.Comment #9
alexpottI think what we need to do is to have something that checks that all the entity level indexes exist if EM::updateFieldStorageDefinition() is called. Discussed with @plach and @jhedstrom on IRC.
Comment #10
plach@effulgentsia:
@alexpott found out what's going, I'm working on a fix. See the following chat:
Comment #11
catchComment #12
plachLet's see whether this works.
This probably needs some additional test coverage, for the PG-specific changes.
Comment #13
catchLovely lovely lovely.
This was only recently added in #2555665: When index is added for content_translation_uid, the corresponding stored schema definition is not updated, I thought the postgres fail looked familiar.
Comment #14
Gábor HojtsyComment #15
plachSilly me
Comment #16
alexpottIt'd be nice if one of the Postgres peeps had a look at this one.
Comment #17
catchThis is a bug on MySQL as well, just our test coverage doesn't catch it:
From http://dev.mysql.com/doc/refman/5.1/en/alter-table.html
So you have column1, column2, column3 in an index.
We drop column2, MySQL silently changes the index definition to be column1, column3.
We add back column2, MySQL does not silently change the index definition to be column1, column2, column3.
Our schema tests only check if the index exists, not if the columns are correct, so MySQL tests pass.
Comment #19
plachFixed the last MySQL failure and improved test coverage. The test-only patch should fail also on MySQL.
I'm working on some test coverage for the PG-specific stuff.
Btw, I tested all the remaining failures on PG locally (VM with Ubuntu 15.04, PHP 5.6.4, and PG 9.4.4) and all tests are green...
Comment #21
alexpott@plach all the other postgres fails are fixed by #2561121: Installer fails on postgresql due to uncaught exception and #2561229: Upgrade content tests fails on postgres for translated comment
Comment #22
plachOk, this should be more or less complete. Reviews welcome :)
Comment #24
catchOverall this looks great, and the optimization to ensure that only dropped/added columns get their indexes rebuilt is necessary - otherwise this could an extremely long time on large tables.
Mostly nitpicks and a couple of questions:
Could this be $index_keys? That would mean one less out of $entity_schema, $schema, $schema_handler and $schema_keys if so.
Or since $schema_keys is only used here, so could maybe directly put the array into the foreach?
When can this happen? Shouldn't that throw an exception or similar if it does? Or a comment would be handy if we're silently ignoring that case for a good reason.
This creates, then drops, but doesn't create again - should it?
Comment #25
plachAttaching also a previous interdiff I was about to post, when I noticed the last review. This fixes also a few notices introduced by the latest patch.
@catch:
3: This was happening before introducing the optimization that skips dropping/creating indexes when creating the entity schema. Theoretically I guess it could happen also if multiple fields are added and a composite index is added at the same time. I added a comment to explain this.
4: Well, creation is handled in the previous
::applyUpdates()
call, but one more cannot hurt.Comment #26
plachComment #29
dawehnerNeeds a comment, why we are doing this here.
It is great to move things into separate methods for readability!
Comment #30
plachWell, it's not only for readability, the method is being invoked in two places actually :)
Comment #31
alexpottAssigning credit to catch (as a reviewer) and myself (as cause of the problem finder)
Comment #32
dawehnerThis has been my concerns
Comment #33
Gábor HojtsyHm, should we believe the postgres fail? (I heard those bots are not predictable(?))
Comment #34
plach@Gábor Hojtsy:
The PG fail was expected, it should be fixed by #2561229: Upgrade content tests fails on postgres for translated comment now. Re-testing.
Btw, #2561121: Installer fails on postgresql due to uncaught exception fixed most of the PG bots randomosity, although I saw one random failure in https://www.drupal.org/pift-ci-job/26901. @alexpott++
Comment #35
alexpott@plach there is a feeling that the first test on postgres might fail because of a DrupalCI timing issue - but it does not happen very often.. I has not occurred on the latest run. So https://www.drupal.org/pift-ci-job/27075 should be the first ever green postgres run.
Comment #36
Gábor HojtsyYay, for first green run :)
Comment #37
alexpottCommitted a173031 and pushed to 8.0.x. Thanks!
Comment #39
Gábor HojtsyYay, thanks all!
Comment #41
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThe primary key of the entity tables was forgotten in this patch, here's a followup for that: #2841291: Fix NOT NULL handling in the entity storage and 'primary key' changes when updating the storage definition of an identifier field