[2.0.x] Fixed #29286 -- Fixed column mismatch crash with QuerySet.values() or values_list() after combining an annotated and unannotated queryset with union(), difference(), or intersection().

Regression in a0c03c62a8ac586e5be5b21393c925afa581efaf.

Thanks Tim Graham and Carlton Gibson for reviews.
Backport of 0b66c3b442875627fa6daef4ac1e90900d74290b from master
This commit is contained in:
Mariusz Felisiak 2018-04-13 12:15:52 +02:00
parent 75a4576e5f
commit 3619d32209
No known key found for this signature in database
GPG Key ID: 2EF56372BA48CD1B
4 changed files with 21 additions and 4 deletions

View File

@ -411,9 +411,8 @@ class SQLCompiler:
# If the columns list is limited, then all combined queries
# must have the same columns list. Set the selects defined on
# the query on all combined queries, if not already set.
if (not compiler.query.values_select and not compiler.query.annotations and
self.query.values_select):
compiler.query.set_values(self.query.values_select)
if not compiler.query.values_select and self.query.values_select:
compiler.query.set_values(tuple(self.query.values_select) + tuple(self.query.annotation_select))
parts += (compiler.as_sql(),)
except EmptyResultSet:
# Omit the empty queryset with UNION and with DIFFERENCE if the

View File

@ -15,3 +15,8 @@ Bugfixes
* Fixed crashes in ``django.contrib.admindocs`` when a view is a callable
object, such as ``django.contrib.syndication.views.Feed`` (:ticket:`29296`).
* Fixed a regression in Django 1.11.12 where ``QuerySet.values()`` or
``values_list()`` after combining an annotated and unannotated queryset with
``union()``, ``difference()``, or ``intersection()`` crashed due to mismatching
columns (:ticket:`29286`).

View File

@ -18,3 +18,8 @@ Bugfixes
* Fixed crashes in ``django.contrib.admindocs`` when a view is a callable
object, such as ``django.contrib.syndication.views.Feed`` (:ticket:`29296`).
* Fixed a regression in Django 1.11.12 where ``QuerySet.values()`` or
``values_list()`` after combining an annotated and unannotated queryset with
``union()``, ``difference()``, or ``intersection()`` crashed due to mismatching
columns (:ticket:`29286`).

View File

@ -1,4 +1,4 @@
from django.db.models import F, IntegerField, Value
from django.db.models import Exists, F, IntegerField, OuterRef, Value
from django.db.utils import DatabaseError, NotSupportedError
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
@ -130,6 +130,14 @@ class QuerySetSetOperationTests(TestCase):
).values_list('num', 'count')
self.assertCountEqual(qs1.union(qs2), [(1, 0), (2, 1)])
def test_union_with_values_list_on_annotated_and_unannotated(self):
ReservedName.objects.create(name='rn1', order=1)
qs1 = Number.objects.annotate(
has_reserved_name=Exists(ReservedName.objects.filter(order=OuterRef('num')))
).filter(has_reserved_name=True)
qs2 = Number.objects.filter(num=9)
self.assertCountEqual(qs1.union(qs2).values_list('num', flat=True), [1, 9])
def test_count_union(self):
qs1 = Number.objects.filter(num__lte=1).values('num')
qs2 = Number.objects.filter(num__gte=2, num__lte=3).values('num')