Fixed #28211 -- Prevented ORing an empty Q() from reducing query join efficiency.

This commit is contained in:
Tom 2017-05-18 19:03:30 +01:00 committed by Tim Graham
parent 1c3a6cec2a
commit bb0b6e5263
2 changed files with 17 additions and 0 deletions

View File

@ -5,6 +5,7 @@ Factored out from django.db.models.query to avoid making the main module very
large and/or so that they can be used by other modules without getting into
circular import difficulties.
"""
import copy
import functools
import inspect
from collections import namedtuple
@ -61,6 +62,14 @@ class Q(tree.Node):
def _combine(self, other, conn):
if not isinstance(other, Q):
raise TypeError(other)
# If the other Q() is empty, ignore it and just use `self`.
if not other:
return copy.deepcopy(self)
# Or if this Q is empty, ignore it and just use `other`.
elif not self:
return copy.deepcopy(other)
obj = type(self)()
obj.connector = conn
obj.add(self, conn)

View File

@ -11,6 +11,14 @@ class QTests(SimpleTestCase):
def test_combine_and_both_empty(self):
self.assertEqual(Q() & Q(), Q())
def test_combine_or_empty(self):
q = Q(x=1)
self.assertEqual(q | Q(), q)
self.assertEqual(Q() | q, q)
def test_combine_or_both_empty(self):
self.assertEqual(Q() | Q(), Q())
def test_deconstruct(self):
q = Q(price__gt=F('discounted_price'))
path, args, kwargs = q.deconstruct()