Opened 10 years ago

Closed 9 years ago

#24142 closed Bug (wontfix)

extra() field overwritten when using union on two querysets

Reported by: dryice Owned by: nobody
Component: Database layer (models, ORM) Version: 1.7
Severity: Normal Keywords: QuerySet.extra
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Here's how to reproduce it:

  • follow step 1 and step 2 of the tutorial to make the Question and Choice model
  • fill in the DB with data:

polls_question;

id question_text pub_date
11112015-01-13 06:05:58
22222015-01-13 06:06:09
33332015-01-13 06:06:17

polls_choice;

id choice_text votes question_id
11aa31
21bb81
32aa92
42bb32
53aa43
63bb23
  • in the Django shell:
    >>> qs = Question.objects.all()
    >>> qs1 = qs.filter(choice__votes__gte=5).annotate(choice_count=Count('choice'))
    >>> for i in qs1:
    ...     print i, i.choice_count
    ...
    111 1
    222 1
    >>> qs2 = qs.exclude(id__in=qs1.values_list("id", flat=True)).extra(select={'choice_count': '1-1'})
    >>> for i in qs2:
    ...     print i, i.choice_count
    ...
    333 0
    >>> for i in qs1 | qs2:
    ...     print i, i.choice_count
    ...
    111 1
    222 1
    333 2
    

Note in the last line, I would expect
333 0
while it gives 333 2

Checking the SQL used:

>>> qs3 = qs1 | qs2
>>> print qs1.query
SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date", COUNT("polls_choice"."id") AS "choice_count" FROM "polls_question" INNER JOIN "polls_choice" ON ( "polls_question"."id" = "polls_choice"."question_id" ) WHERE "polls_choice"."votes" >= 5 GROUP BY "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date"

>>> print qs2.query
SELECT (1-1) AS "choice_count", "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE NOT ("polls_question"."id" IN (SELECT U0."id" FROM "polls_question" U0 INNER JOIN "polls_choice" U1 ON ( U0."id" = U1."question_id" ) WHERE U1."votes" >= 5 GROUP BY U0."id", U0."question_text", U0."pub_date"))

>>> print qs3.query
SELECT (1-1) AS "choice_count", "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date", COUNT("polls_choice"."id") AS choice_count FROM "polls_question" LEFT OUTER JOIN "polls_choice" ON ( "polls_question"."id" = "polls_choice"."question_id" ) WHERE ("polls_choice"."votes" >= 5 OR NOT ("polls_question"."id" IN (SELECT U0."id" FROM "polls_question" U0 INNER JOIN "polls_choice" U1 ON ( U0."id" = U1."question_id" ) WHERE U1."votes" >= 5 GROUP BY U0."id", U0."question_text", U0."pub_date"))) GROUP BY "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date", (1-1)

It looks the "|" operator didn't check if there's extra field with the
same name on the two sides, and
COUNT("polls_choice"."id") AS choice_count
overwrote
SELECT (1-1) AS "choice_count"

I understand once we started using extra() we are on the edge. But
maybe this is something that could be fixed? Thanks!

Change History (4)

comment:1 by Tim Graham, 10 years ago

Triage Stage: UnreviewedAccepted

Maybe it can be fixed, but the latest thinking I've heard is that we're trying to make the functionality of extra() available through better APIs so we can deprecate it, so please don't be surprised if this gets a "won't fix".

comment:2 by dryice, 10 years ago

Thanks! It's great to hear something better is planned :)

comment:3 by Tim Graham, 9 years ago

Keywords: QuerySet.extra added

comment:4 by Tim Graham, 9 years ago

Resolution: wontfix
Status: newclosed

We are no longer fixing bugs with QuerySet.extra() per discussion on django-developers.

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