1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

Fixed #31792 -- Made Exists() reuse QuerySet.exists() optimizations.

The latter is already optimized to limit the number of results, avoid
selecting unnecessary fields, and drop ordering if possible without
altering the semantic of the query.
This commit is contained in:
Simon Charette
2020-08-12 23:16:22 -04:00
committed by Mariusz Felisiak
parent 7f4c9222df
commit 51297a9232
4 changed files with 29 additions and 8 deletions

View File

@@ -1145,11 +1145,9 @@ class Exists(Subquery):
output_field = fields.BooleanField()
def __init__(self, queryset, negated=False, **kwargs):
# As a performance optimization, remove ordering since EXISTS doesn't
# care about it, just whether or not a row matches.
queryset = queryset.order_by()
self.negated = negated
super().__init__(queryset, **kwargs)
self.query = self.query.exists()
def __invert__(self):
clone = self.copy()

View File

@@ -1127,9 +1127,6 @@ class SQLCompiler:
Backends (e.g. NoSQL) can override this in order to use optimized
versions of "query has any results."
"""
# This is always executed on a query clone, so we can modify self.query
self.query.add_extra({'a': 1}, None, None, None, None, None)
self.query.set_extra_mask(['a'])
return bool(self.execute_sql(SINGLE))
def execute_sql(self, result_type=MULTI, chunked_fetch=False, chunk_size=GET_ITERATOR_CHUNK_SIZE):

View File

@@ -522,7 +522,7 @@ class Query(BaseExpression):
def has_filters(self):
return self.where
def has_results(self, using):
def exists(self):
q = self.clone()
if not q.distinct:
if q.group_by is True:
@@ -533,6 +533,12 @@ class Query(BaseExpression):
q.clear_select_clause()
q.clear_ordering(True)
q.set_limits(high=1)
q.add_extra({'a': 1}, None, None, None, None, None)
q.set_extra_mask(['a'])
return q
def has_results(self, using):
q = self.exists()
compiler = q.get_compiler(using=using)
return compiler.has_results()