Change record: https://www.drupal.org/node/2708973
If an entity query uses ->allRevisions() the base_table and data_table are not queried, only the revision_table and revision_data_table are. This means fields that are not revisionable are not able to be queried.
Take this hypothetical example:
$this->entityTypeManager->getStorage($entity_type_id)
->getQuery()
->allRevisions()
->condition('foo', 'bar')
->execute();
If I have added a field foo to all entity types, which is not revisionable, and I want to return all revisions of a given entity type where foo equals bar. This would throw an error such as:
Uncaught PHP Exception Drupal\\Core\\Entity\\Query\\QueryException: "'foo' not found" at core/lib/Drupal/Core/Entity/Query/Sql/Tables.php line 25
Why is this so important?
This is currently blocking Multiversion and Workbench Moderation from working together. Multiversion makes all content entities revisionable, but not all fields revisionable. It even adds non-revisionable fields to revisionable entities, because sometimes it makes sense, especially for "meta" kinds of data. For example in Multiversion the workspace an entity belongs to is a non-revisionable field, we don't want to allow different revisions of an entity to belong to different workspaces, this will cause all kinds of pain.
Workbench Moderation only really cares about revisions, it even allows you to create forward revisions, these are revisions newer than the current default revision. Therefore when looking for the newest revision Workbench Moderation uses an allRevisions() query. Multiversion hooks into this and adds a condition for the workspace field and which is when we get a Uncaught PHP Exception Drupal\\Core\\Entity\\Query\\QueryException: "'workspace' not found" issue.
I expect there will be many more cases where this will come up in the future.
| Comment | File | Size | Author |
|---|---|---|---|
| #22 | allrevisions_entity-2700261-22.patch | 10.99 KB | timmillwood |
Comments
Comment #2
timmillwoodHere is a simple test to show the issue.
In there test two entities are created, on these the user is changed and translations are added. It then queries for all revisions and gets both revisions for both entities. It then queries for all revisions where the non-revisionable field is set to
bar, it should just return the two revisions for the first entity, but it throws an error:Comment #4
timmillwoodAdding a fix for the test uploaded in #2.
Also adding another test to test the same issue on non-translatable entities.
Comment #8
timmillwoodIt works locally ;)
Comment #9
timmillwoodLooks like the patch was missing an entity_test entity type.
Comment #10
dixon_Just a quick initial review below. I'll do a more detailed review later today hopefully.
Lets rename this new test entity type to something more descriptive, like
EntityTestMulRevNonRevFieldSame here, let's use the more descriptive name as suggested above.
Double empty line
Comment #11
timmillwoodUpdated with changes from #10 and also simplified the implementation a little.
Comment #12
timmillwoodFiling against 8.1.x as 8.0.x is now frozen, although it passes against 8.0.x, 8.1.x, and 8.2.x.
Comment #13
amateescu commentedI could find only some small things to fix, except the first point which I think is pretty important, so marking NW for that.
Can't we add these fields to the existing EntityTestMulRev and EntityTestRev classes?
We already have a lot of these entity test classes for which we (unnecessarily) create the db tables on every test method run and it would be a shame to add even more for just this test.
Doesn't seem to be used in this file.
The parent test class already adds everything in this list, except 'language', so we should add only that module in this list.
Based on point 1. above, these might need to be renamed to use the ..MulRev and ..Rev classes.
Enable *two* additional languages? :)
I don't think we need the parenthesis around 'and translatable', it's not like we're testing both scenarios in this method.
Comment #14
timmillwoodApplying all changes suggested in #13.
Comment #15
timmillwoodComment #17
timmillwoodFixing the serialization test I broke.
Comment #19
timmillwoodFurther serialization issues fixed.
Comment #20
timmillwoodRe-rolling to make sure it still applies cleanly.
Comment #21
amateescu commentedOk, getting close :)
Needs an empty line before the use statements, but based on the comment below, both use statements will not be needed anymore.
The 'non_rev_field' is already provided by the parent class (EntityTestRev) so we don't really need to add here as well, no?
A recent change in the coding standards says that we should not provide a @file docblock anymore :)
Comment #22
timmillwoodImplemented changes in #21.
Comment #23
amateescu commentedNice, looks great now.
P.S.: An interdiff would have been helpful :)
Comment #24
timmillwoodComment #25
timmillwoodComment #26
alexpottAdding this to the rc target triage list so the committers can discuss before 8.1.0 is released.
Comment #27
effulgentsia commentedRe #26, I think this would be very good to get into 8.1, since it's a blocker for the contrib modules mentioned in the summary. However, I think it might be patch-safe, so could go into 8.1.1 instead of 8.1.0. Except that it changes db queries, which might introduce some side-effect on production sites (e.g., performance?), in which case much better to do during a minor update than a patch update. So I don't know. Opinions from folks on this issue?
Comment #28
xjmSo @catch and I discussed this and agreed that specific database queries could be considered a (very) internal API, and therefore there is a slight risk of disruption in patch releases (e.g. for a module performing a query alter). (https://www.drupal.org/core/d8-bc-policy#schema says "Writing queries directly against core tables is not recommended and may result in code that breaks between minor versions", which sort of implies that such things won't break between patch releases, so I think we'd want to apply the same logic here.) So, we agreed to make this an RC target.
If it does not land in the next 12h, we should probably commit it for 8.1.1 anyway, create a CR, and mention it in the release notes, since the risk of disruption is theoretical and the bug is problematic.
Comment #29
catchYeah I don't think the theoretical risk of broken query alters is very likely. However I also don't feel at all confident that we have test coverage of such things, which has made me a bit reticent to commit the patch so far.
The theoretical risk of performance degradation doesn't make this any better for 8.1.0 than 8.1.1 - that's what the RC period was for to flush things like that out, but it puts me closer to committing it just after 8.1.0 is tagged.
Comment #30
timmillwoodInitial draft of change record added: https://www.drupal.org/node/2708973
Comment #32
timmillwoodComment #33
amateescu commentedIt was rtbc before.
Comment #34
alexpottCommitted 442799a and pushed to 8.1.x and 8.2.x. Thanks!
I agree with @catch I think the query alter issues are theoretical. In fact I'm not sure any queries that were working will actually change - it's just that things that didn't work now do.