#24142: extra() field overwritten when using union on two querysets
----------------------------------------------+--------------------
Reporter: dryice | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: 1.7
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+--------------------
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 =||
|| 1||111||2015-01-13 06:05:58 ||
|| 2||222||2015-01-13 06:06:09 ||
|| 3||333||2015-01-13 06:06:17 ||
polls_choice;
|| id =||= choice_text =||= votes =||= question_id =||
|| 1||1aa||3||1 ||
|| 2||1bb||8||1 ||
|| 3||2aa||9||2 ||
|| 4||2bb||3||2 ||
|| 5||3aa||4||3 ||
|| 6||3bb||2||3 ||
- 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!
--
Ticket URL: <https://code.djangoproject.com/ticket/24142>
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 post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/049.f570584151086be05e1fcea32b1e9bbd%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.