If a base field was overwritten in bundlefieldDefinition() just like comment, drupal core's Tables->addfield() function can't get the right target type when jsonapi filter this kind of field.
ps: because entity reference's default target type is node, so we shouldn't use node to test it.
This can be produced on comment just in core.
- make a comment type named "tcomment", and Target entity type set to "Taxonomy term".
- add a comment field to vocabulary "tags", and set Comment type to "tcomment".
- Add a entity_reference field to tags, set machine name as field_user and target to user.
- Create a tag named "foo" and create a comment for it.
- GET /jsonapi/comment/tcomment?include=entity_id&filter[entity_id.name][value]=foo will get error
"errors": [
{
"title": "Internal Server Error",
"status": 500,
"detail": "'name' not found",
"links": {
"info": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1"
},
"code": 0,
Group has this problem too.
Bug reproduced process on group:
- Install drupal8.5.x jsonpi group
- Create a group type and add a group
- Create a group type and add a group
- /jsonapi/group_content/demotype-group_membership?include=entity_id&filter[entity_id.name][value]=admin
Got error:"errors": [ { "title": "Internal Server Error", "status": 500, "detail": "'name' not found", "links": { "info": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1" }, "code": 0,
But if I request
/jsonapi/group_content/demotype-group_membership?include=uid&filter[uid.name][value]=admin
I will get the right result.
Meanwhile If I request group_node
/jsonapi/group_content/business-group_node-device?include=entity_id&filter[entity_id.uuid][value]=4477a3ba-94b2-4a4c-96d3-8325e3d4e4e3
I will get
"errors": [
{
"title": "Internal Server Error",
"status": 500,
"detail": "'promotion_id' not found",
"code": 0,


Comments
Comment #2
lawxen commentedComment #3
skyredwangI was able to reproduce the first error on simplytest.me. The log shows:
Drupal\Core\Entity\Query\QueryException: 'name' not found in Drupal\Core\Entity\Query\Sql\Tables->ensureEntityTable() (line 348 of /home/d5td/www/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php).Comment #4
lawxen commentedThis can be reproduced just in core too.
Comment #5
lawxen commentedComment #6
skyredwangComment #7
e0ipsoWhat is
entity_idin this context? It's probably something internal to the Comment implementation, but I'm not familiar with it.Comment #8
skyredwangBelow is a sample output from a sandbox, `entity_id` to client side developer is just another relationship
Comment #9
lawxen commented@e0ipso In the issue summary's example about comment, entity_id represent taxonomy_term--tags
This is /jsonapi/comment/tcomment?include=entity_id result:
Comment #10
lastlink commentedI'm having a similar issue w/ trying to create a comment of a comment of a comment of a node. This last comment won't create giving me a "This entity (comment: 35) cannot be referenced." error, but I can create then directly on the web and the comments above all create fine. Does jsonapi only support a depth of 2 comments types right now?
Comment #11
lawxen commentedI create another issue about config entity's filter, After several hours's investigation, I find it duplicate with this issue, I must close one and I choose close this one:)
Comment #12
lawxen commentedComment #13
lawxen commentedJsonapi dosn't support filter nested config entity, fully described here: https://www.drupal.org/project/jsonapi/issues/2959445
This issue's root problem part same with it, But have some difference with it, so reopen it.
Detail:
/jsonapi/group_content/business-group_promotion?include=entity_id&filter[entity_id.promotion_id][value]=1
1. group_content has a base field "entity_id" and set target with group_type .
2. each group_content bundle will override the entity_id field and set the entity_id with custom target type.
3. The url will eventually equal to execute
$query = \Drupal::entityTypeManager()->getStorage('group_content')->getQuery();
$query->condition('entity_id.entity.promotion_id', '1','=')->execute();
4. The drupal core will
We can see the final query don't get the bundle's entity_id field, but get the original entity_type's field.
Then
$field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);($entity_type_id = group_type) will get error:just like Content entity query following a reference to a config entity cannot be queried ,
Even through Content entity query following a reference to a config entity cannot be queried be fixed, This issue can't be fixed. So I must reopen this issue.
Comment #14
lawxen commentedComment #15
lawxen commentedComment #16
lawxen commentedThis issue has nothing relation with filtering config entity.
Comment #17
wim leersThanks for the detailed bug report, and the discussion in the comments! This has been most helpful :)
Based on the IS, this sounds related to #2958587: Unable to filter on columns of entity reference fields, which just got fixed.
But based on #13, this is a bug in
\Drupal\Core\Entity\Query\Sql\Tables::addField()? Digging in more…Comment #18
wim leersComment #19
wim leersReproduced with the steps to reproduce. Debugging now. Also making a slight clarification to the STR in the IS.
Comment #20
wim leers(Note this also means #2958587: Unable to filter on columns of entity reference fields did not fix it.)
Comment #21
wim leersTo be 100% clear: I can reproduce the failure when testing with
/jsonapi/comment/tcomment?include=entity_id&filter[entity_id.name][value]=big.I stepped through the code with a debugger. JSON API correctly expands
entity_id.nametoentity_id.entity.name. It's deep in the entity query system that things fail.Now,
\Drupal\Core\Entity\Query\QueryInterface::condition()'s docs say this:Specifically the Additionally, the target entity type can be specified by appending the ":target_entity_type_id" to "entity". caught my attention. Why do we support this? But first let's try my hunch: I added this at the top of
\Drupal\Core\Entity\Query\Sql\Tables::addField():This is equivalent to "hinting" to the entity query system what the target entity type will be. And guess what? Suddenly things worked! I'm very very much suspecting that this is caused by the two referencable entity types from
tcommentbeinguserandtaxonomy_term, and both have anamefield! Still, from theentity_idfield ontcommententities, only thetaxonomy_termentity type can be referenced, so it shouldn't be confused by this.Digging deeper…
Comment #22
wim leersAha, that particular line that stood out to me was added in #2424791: Entity query hardcodes entity_reference and entity specifier!
Comment #23
wim leersThe problem definitely lies in
\Drupal\Core\Entity\Query\Sql\Tables::addField(), but it's extremely complex.The first call to
::addField(), all goes well. But the second time around,$entity_type_id === 'node', which of course does not make sense; we're only dealing withcomment,taxonomy_termanduserhere! So how could we POSSIBLY end up withnode?!Due to the recursion used this was extremely hard to pinpoint.
@caseylau already alluded to the root cause though: the
$field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);call. It returns seemingly correct data … but actually that's not the case.So, the first call to
::addField(), all seems well. But what's crucial is that at the end of the call to::addField(), we set up things for the second call:And this seems fine too, and actually would be fine. If it weren't for the fact that it's setting
$entity_typebased on data in$field_storage. And the data in$field_storageis very wrong:So I'd love to say: "the entity query system is BROKEN! Not up to JSON API to fix this!". But … AFAICT the entity query system is designed to work at the entity type level, not the bundle level! Zero mentions of "bundle" in
\Drupal\Core\Entity\Query\QueryInterface.Basically, AFAICT, #2424791: Entity query hardcodes entity_reference and entity specifier was necessary for https://www.drupal.org/project/dynamic_entity_reference fields in general, but a bundle/configurable field (non-base field) on an entity type that is an entity reference and configures different target entity reference types is equivalent to a https://www.drupal.org/project/dynamic_entity_reference field from a querying POV!
It'd be great to have this confirmed by an Entity API/Entity Query API expert.
Comment #24
wim leersWe can fix this by having JSON API automatically generate the syntax introduced by #2424791: Entity query hardcodes entity_reference and entity specifier. JSON API's
FieldResolvercan reliably determine the target entity type thanks toin
\Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::propertyDefinitions().(Many thanks to #2064191: Fix the 'target_bundle' field setting - 'target_bundles' are not validated when entity_reference is enabled for adding that comment. Also see #2064191-48: Fix the 'target_bundle' field setting - 'target_bundles' are not validated when entity_reference is enabled for prior complaints about bundles +
Tables::addField(), which already was infamous back then.)All of that writing and research eventually results in this … one-liner 😆 Well, tests are of course still necessary :)
@caseylau, please test this patch!
Comment #25
wim leersComment #27
lawxen commented@Wim Leers
Thanks for the digging,
I test 2953207-24.patch, it works for this issue's filter。
But after apply the patch, issue: Inclusion of nested relationships fails for bundle-specific fields 's problem come back.
/jsonapi/comment/forterm?include=entity_id,entity_id.field_myuser/jsonapi/group_content/business-group_product-default?entity_id,entity_id.field_product_vocabularyinclude won't get the nested level result. Now that the resolution has been found, "nested include issue" can be easily fixed, Great works:).
Comment #28
wim leersUpdated
FieldResolverTestto now expect the more specific entity query expressions!Note that based on the expectations I had to update, I don't have confidence in my patch being 100% correct. Because only the
uid.namecase is getting the target entity type ID set; any filter expression that already includesentity(e.g.uid.entity.name) will NOT get it in the current patch. I think that's something best left to the person who knowsFieldResolverbest: @gabesullice.Comment #30
wim leersDown to one fail, yay! Let's get it down to zero.
Comment #31
wim leers#27: that problem should be fixed by #30 — the failure in
\Drupal\Tests\jsonapi\Functional\JsonApiFunctionalTest::testRead()caught that :)#2953321: Comprehensive JSON API integration test coverage phase 5: nested includes and sparse field sets will massively expand the test coverage for this.
Comment #32
gabesulliceThis looks good except for one thing, let's use the data definitions instead of the "more likely to change" constraint.
I'm happy to see that the "ambiguous" code is already going to prove more useful. Perhaps this is a real use case that we can test, rather than making our own field (as per #2971281: Test coverage: ambiguous filter expression paths)
Comment #33
lawxen commentedI have tested the latest patch, both works on nested include and filter on bundle overwritten entity reference field.
Comment #34
wim leersinstanceof DataReferenceDefinitionInterface… but we're callinggetEntityTypeId().Shouldn't we do:
?
Comment #35
gabesulliceHm, it's kind of an impossibility given that entity references should only reference entities. So, I was sort of counting on the code to blow up if non-entity data was every encountered in the hope that we would one day be alerted to a real world example, but that's bad DX.
What do you think of throwing an exception like: "Filtering or including data in the path $path is not supported. Please report this incident in the JSON API issue queue."
Comment #36
gabesulliceComment #37
wim leersThat makes sense (entity references should only reference entities). I tried to do what you suggested, but didn't like the end result (see attached
interdiff-nope.txt). But then I realized that this is exactly whatassert()is for! What do you think ofinterdiff.txt?Comment #38
gabesullice❤️
Comment #39
wim leersLet me try to get test coverage going first :)
Comment #40
wim leersThe failing test is also the interdiff. Regression test coverage modeled after
\Drupal\Tests\big_pipe\FunctionalJavascript\BigPipeRegressionTest(). That makes it very easy to add regression tests for complex scenarios that require particular setup.Comment #42
gabesulliceThis is a really nice pattern.
Comment #43
wim leers❤️
I found some more nits that I'll fix, but that means I can get this committed today, yay!
Comment #44
wim leersFixed nits.
Comment #45
wim leersCrediting the people who materially helped shape this patch.
Comment #47
wim leersStill green, so … committed!
Comment #48
skyredwang@caseylau found a bug to this patch, he needs to supply additional test and patch to fix it.
Comment #49
lawxen commentedcommit #46 make some complex include don't work.
git reset --hard f118327b86dbd0ea1a11e9f5fd678b6e3db76734I will get the right result.
No vid info.
git reset --hard f118327b86dbd0ea1a11e9f5fd678b6e3db76734I will get the right result.
Comment #50
wim leers#48/#49: This was committed in #46 and released. Please create a new issue for this newly discovered problem! Otherwise it's impossible to find the discussion associated with a given commit.
Comment #53
wim leers#49: I think you never got around to filing that, @caseylau? If you did, it was never referenced here.
It just happens to be that @effulgentsia asked a great question in #3040280-22: FieldResolver::resolveInternalIncludePath() does not handle resolving a single public include path to multiple internal include paths that required some issue queue digging. I ended up on this issue again and … happened to see #49. I'm 95% certain that the problem you're reporting is the same problem we just fixed in #3040280: FieldResolver::resolveInternalIncludePath() does not handle resolving a single public include path to multiple internal include paths :)
Comment #54
lawxen commented@Wim Leers (I just change my name to KaysenLau, because there's many duplicate "caseylau" in China😀)
Yeah, I forgot to got around to filing that
I had created a new issue for #49 on
#2973681: Regression introduced by #2953207: Deep nested include on multi target entity type field fail and not point this information on this issue, my mistake.
#49 has been fixed on #2973681
Seems like it's been optimized again in #3040280: FieldResolver::resolveInternalIncludePath() does not handle resolving a single public include path to multiple internal include paths
Comment #55
rpayanmMoving to Drupal core's issue queue.
I'm working on https://www.drupal.org/project/drupal/issues/3122113