Opened 7 years ago

Closed 3 years ago

Last modified 2 months ago

#29338 closed Bug (fixed)

Can't use OuterRef in union Subquery

Reported by: Matthew Pava Owned by: Mariusz Felisiak
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Jeff, Can Sarıgöl, InvalidInterrupt Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When you make a QuerySet using the union method or the | operator, the QuerySet passed into the union method cannot reference OuterRef even when wrapped with Subquery.

For example:

cls = Document.objects.filter(
    checklist__isnull=False,
    part=OuterRef('id')
).values('checklist__customer', 'created')

ots = Document.objects.filter(
    ownershiptransfer__isnull=False,
    part=OuterRef('id')
).values('ownershiptransfer__ship_target__contact', 'created')

return self.annotate(
    owner=Subquery(cls.union(ots).values('owner')[:1])
)

Returns this error:

ValueError
This queryset contains a reference to an outer query and may only be used in a subquery.

I get the same error with this statement:

return self.annotate(
    owner=Subquery((cls | ots).values('owner')[:1])
)

(As an aside, I also get an error when I try to apply an order_by clause.)

Change History (19)

comment:1 by Tim Graham, 7 years ago

Are you sure that generating some sensible SQL for this queryset is possible?

comment:2 by Matthew Pava, 7 years ago

Yes, it is possible to generate SQL for this query. I tried it myself. ...I suppose "sensible" is a subjective term.

I just tried using an __in lookup, but that was getting to be a struggle.

Maybe Subquery wasn't originally intended to be used with unions, but I think it would be a good feature to have, especially in the discussion of CTEs (common table expressions).

comment:3 by Tim Graham, 7 years ago

Triage Stage: UnreviewedAccepted

comment:4 by Jeff, 7 years ago

Cc: Jeff added

comment:5 by Can Sarıgöl, 6 years ago

Cc: Can Sarıgöl added
Has patch: set

hi, I thought that we can use union queries in subqueries by replacing the alias from origin query to union queries. I've pushed a commit. if this approach is ok, I can add other tests and go further? PR

in reply to:  description comment:6 by Can Sarıgöl, 6 years ago

cls = Document.objects.filter(
    checklist__isnull=False,
    part=OuterRef('id')
).values('checklist__customer', 'created')

ots = Document.objects.filter(
    ownershiptransfer__isnull=False,
    part=OuterRef('id')
).values('ownershiptransfer__ship_target__contact', 'created')

return self.annotate(
    owner=Subquery(cls.union(ots).values('owner')[:1])
)

I change the example like this:

cls = Document.objects.filter(
    checklist__isnull=False,
).values('checklist__customer', 'created')

ots = Document.objects.filter(
    ownershiptransfer__isnull=False,
).values('ownershiptransfer__ship_target__contact', 'created')

return self.annotate(
    owner=Subquery(cls.union(ots).filter(part=OuterRef('id')).values('owner')[:1])
)

comment:7 by Tobias Kunze, 6 years ago

Owner: changed from nobody to Can Sarıgöl
Status: newassigned

comment:8 by Can Sarıgöl, 6 years ago

I forgot it, thanks.

comment:9 by Asif Saifuddin Auvi, 6 years ago

Version: 2.0master

comment:10 by Can Sarıgöl, 6 years ago

Owner: Can Sarıgöl removed

comment:11 by Mariusz Felisiak, 6 years ago

Patch needs improvement: set

comment:12 by Mariusz Felisiak, 6 years ago

Status: assignednew

comment:13 by Mariusz Felisiak, 5 years ago

comment:14 by Mariusz Felisiak, 5 years ago

Owner: set to Mariusz Felisiak
Patch needs improvement: unset
Status: newassigned

comment:15 by Mariusz Felisiak, 5 years ago

Patch needs improvement: set

comment:16 by InvalidInterrupt, 4 years ago

Cc: InvalidInterrupt added

comment:17 by Mariusz Felisiak, 3 years ago

Patch needs improvement: unset

comment:18 by GitHub <noreply@…>, 3 years ago

Resolution: fixed
Status: assignedclosed

In 30a01441:

Fixed #29338 -- Allowed using combined queryset in Subquery.

Thanks Eugene Kovalev for the initial patch, Simon Charette for the
review, and Chetan Khanna for help.

comment:19 by GitHub <noreply@…>, 2 months ago

In 53ea4cce:

Fixed #35744 -- Relabelled external aliases of combined queries.

Just like normal queries, combined queries' outer references might fully
resolve before their reference is assigned its final alias.

Refs #29338.

Thanks Antony_K for the report and example, and thanks Mariusz Felisiak
for the review.

Note: See TracTickets for help on using tickets.
Back to Top