#29545: Nested OuterRef not looking on the right model for the field.
-------------------------------------+-------------------------------------
Reporter: Aaron Lisman | Owner: Simon
| Charette
Type: Bug | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: outerref, subquery | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Simon Charette):
* status: new => assigned
* owner: nobody => Simon Charette
Comment:
This is more of a brain dump than a final resolution but I think I might
have nailed it down. I thought I'd share how I came with what I believe is
the solution to share a bit of knowledge about how the ORM resolves
expressions.
By breaking the query construction in multiple statements and adding
breakpoints in `OuterRef.resolve_expression` and
`ResolvedOuterRef.resolve_expression` I noticed that the latter was being
called '''after''' the complete query construction when it was being
executed which should not happen. In short all expressions should be
resolved to their '''final''' expression at this point and in the case of
`OuterRef` and `ResolvedOuterRef` they should be `Col` instances.
I then assumed that something must not be have been esolved properly so I
added a breakpoint before the `print(qs)` and dug into `qs.query`
internals. By walking the chain of
`qs.query.annotations['has_item'].query` I noticed that
`.where.children[0].lhs` was and `Exist` instance and that its
`.query.where.children[0].rhs` happened to be a `ResolvedOuterRef`
instance. I then knew that this was the culprit as it should have been a
`Col` by this point. I also noticed that the copy of the `Exists` present
as the `.has_tag` expression had its `.query.where.children[0].rhs`
correctly resolved to a `Col` so I adjusted the test to replace the
unresolved reference to the `Col` and got the test passing.
{{{#!python
def test_nested_outerref(self):
number = Number.objects.create(num=5)
Node.objects.create(num=5)
nested_query = Node.objects.filter(num=OuterRef(OuterRef('num')))
nested_exist = Exists(nested_query)
query = Item.objects.annotate(
has_tag=nested_exist,
).filter(has_tag=True)
exists = Exists(query)
qs = Number.objects.annotate(
has_item=exists
)
col =
qs.query.annotations['has_item'].query.annotations['has_tag'].query.where.children[0].rhs
qs.query.annotations['has_item'].query.where.children[0].lhs.query.where.children[0].rhs
= col
print(str(qs.query))
self.assertEqual(qs.get(), number)
}}}
From that point I knew that there was an issue resolving
`qs.query.annotations['has_item'].query.where.children[0].lhs` and then I
remembered that `sql.Where.resolve_expression` was performing resolving
for `.rhs` of lookups but not for `.lhs` which brought me to
[https://github.com/django/django/compare/master...charettes:ticket-29545
this still incomplete patch] that happens to solve this issue and pass the
test suite on SQLite so far.
I've assigned the ticket to myself as I plan to submit the above branch
for review in the next days. I wouldn't be surprised if it fixed a other
issues related to subqueries and `OuterRef`.
--
Ticket URL: <https://code.djangoproject.com/ticket/29545#comment:7>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/063.d2282a1bbfe2eb29938c13024f44ab87%40djangoproject.com.