Browse Source

Fixed #30771 -- Fixed exact lookup against queries with selected columns.

Use pre-existing select fields (and thereby GROUP BY fields) from
subquery if they were specified, instead of always defaulting to pk.

Thanks Aur Saraf for the report and Simon Charette for guidance.
James Timmins 5 years ago
parent
commit
0719edcd5f
3 changed files with 17 additions and 3 deletions
  1. 1 0
      AUTHORS
  2. 3 3
      django/db/models/lookups.py
  3. 13 0
      tests/lookup/tests.py

+ 1 - 0
AUTHORS

@@ -384,6 +384,7 @@ answer newbie questions, and generally made Django that much better:
     James Bennett <james@b-list.org>
     James Murty
     James Tauber <jtauber@jtauber.com>
+    James Timmins <jameshtimmins@gmail.com>
     James Wheare <django@sparemint.com>
     Jannis Leidel <jannis@leidel.info>
     Janos Guljas

+ 3 - 3
django/db/models/lookups.py

@@ -262,9 +262,9 @@ class Exact(FieldGetDbPrepValueMixin, BuiltinLookup):
         from django.db.models.sql.query import Query
         if isinstance(self.rhs, Query):
             if self.rhs.has_limit_one():
-                # The subquery must select only the pk.
-                self.rhs.clear_select_clause()
-                self.rhs.add_fields(['pk'])
+                if not self.rhs.has_select_fields:
+                    self.rhs.clear_select_clause()
+                    self.rhs.add_fields(['pk'])
             else:
                 raise ValueError(
                     'The QuerySet value for an exact lookup must be limited to '

+ 13 - 0
tests/lookup/tests.py

@@ -5,6 +5,7 @@ from operator import attrgetter
 
 from django.core.exceptions import FieldError
 from django.db import connection
+from django.db.models import Max
 from django.db.models.expressions import Exists, OuterRef
 from django.db.models.functions import Substr
 from django.test import TestCase, skipUnlessDBFeature
@@ -956,3 +957,15 @@ class LookupTests(TestCase):
             ),
         )
         self.assertEqual(qs.get(has_author_alias_match=True), tag)
+
+    def test_exact_query_rhs_with_selected_columns(self):
+        newest_author = Author.objects.create(name='Author 2')
+        authors_max_ids = Author.objects.filter(
+            name='Author 2',
+        ).values(
+            'name',
+        ).annotate(
+            max_id=Max('id'),
+        ).values('max_id')
+        authors = Author.objects.filter(id=authors_max_ids[:1])
+        self.assertEqual(authors.get(), newest_author)